Get the exact point in which a Polygon Intersects with a polyline - sql-server

I would like to ask you something regarding Intersection on SQL Server.
I am running a project in which I am using a gmap. I have a polygon through which some polylines are passing through and some are not. I am using the STIntersection in order to get the exactly part of polyline which is in the polygon.
Below is the t-sql that I am using to achieve this.
The issue now is that I want to find the exactly point in which each polyline touches the polygon through passing out. Do you have any workaround concerning this?
DECLARE #polygon geography;
DECLARE #polyline geography;
SET #g = (select Polygon from Polygons where id = #polygonID)
SET #h = (select GeogPolyline from Polylines where ID = #polylineId)
SET #intersectedpart = (SELECT #g.STIntersection(#h).STAsText() )

I manage to resolve this using the below :
SET #result = (SELECT #g.STIntersection(#h).STStartPoint())
Using this you are geting the first point of intersection between the polyline and polygon

Related

SSRS 2012 display Bing map image

I have created sql to retrieve information from our table and create the url for a Bing map. If I take the url from the query and paste it into a browser the map image appears.
Example: https://dev.virtualearth.net/REST/V1/Imagery/Map/Road?mapSize=600,600&mapLayer=TrafficFlow&format=png&pushpin=35.96981750,-85.03747790;64;1&key=xxx
But in SSRS if I use the url as an external image I get the red-X-in-box. No error message but no image either.
I read there should be a way to "enable external images". I've checked the box for the image. Is there another place to change the setting?
I can produce your map without any issues. Follow these instructions and make sure you can reproduce the same results, , then compare to your own report. Hopefully the issue will become apparent.
Create a new Report.
Create a new Dataset called BingMapSample and use the following dataset query, swapping the key for your Bing maps key
-- set up some static values
DECLARE #BingmapKey varchar(256) = 'XxXX-99x-
9XXXXX9XXxxxXXXxXxXxxxxXxXxx9X9XxxX9xxXxXX9xXXx99x9XXxx'
DECLARE #MapSize varchar(10) = '600'
DECLARE #Layer varchar(256) = 'TrafficFlow'
-- stick a few locations in a table, the first one is from your exmaple
DECLARE #mapLocations TABLE (coords varchar(256))
INSERT INTO #mapLocations VALUES
('35.96981750,-85.03747790'),
('50.998647,-0.105406')
-- now build up some urls to use in the report
SELECT
'https://dev.virtualearth.net/REST/V1/Imagery/Map/Road?mapSize=' + #MapSize + ',' + #MapSize
+ '&mapLayer=' + #Layer
+ '&format=png&pushpin=' + ml.coords
+ ';64;1&key=' + #BingmapKey
AS BingMapSampleURL
FROM #mapLocations ml
Now add an image to your report (use a sensible size) and set the following
Source = External
Value = =First(Fields!BingMapSampleURL.Value, "BingMapSample")
If you run the report you should see your map displayed.
To show both maps in a list, do the following
Add a 'List' to your report and set
DataSetName = BingMapSample
Resize the list's only cell to something sensible then inside the list 'cell' insert an image. Set the image properties as follows
Source = External
Value = =Fields!BingMapSampleURL.Value
The final design looked like this... (I shaded the list background just for clarity).
If you run the report you should now also see two more maps, three maps in total.
When I run the report I get this
Hope that helps...

SQL Geography Datatype , checking Point in Polygon , STIntersects producing wrong result

I am trying to check point in polygon, but STIntersect producing wrong result, below is given both point and polygon.
DECLARE #point GEOGRAPHY = GEOGRAPHY::Point(25.631119, 54.666181, 4326)
DECLARE #polygon GEOGRAPHY = GEOGRAPHY::STGeomFromText('POLYGON
((55.368827104612151 25.270499845366924, 55.368226289792808
25.268578811810126, 55.367410898252288 25.269529630198974,
55.368054628415855 25.270364015710307, 55.368827104612151
25.270499845366924))', 4326)
SELECT #polygon.STIntersects(#point), #point.STIntersects(#polygon)
Result is returning 1, however it should return 0, because i pick the point out side of fence,,
Am I making anything wrong with polygon coordinates? Please advice me for any stupid mistake of mine as I am new in spatial data types.
In order to "fix" this, we need to make some form of assumption. If the assumption cannot be "instruct the users to enter polygons that obey the left-hand rule" then we have to use something else.
Here, I'm assuming that the correct "sense" for the polygon is whichever way around means that it's enclosing the smallest area:
DECLARE #point GEOGRAPHY = GEOGRAPHY::Point(25.631119, 54.666181, 4326)
DECLARE #polygon GEOGRAPHY = GEOGRAPHY::STGeomFromText('POLYGON
((55.368827104612151 25.270499845366924,
55.368226289792808 25.268578811810126,
55.367410898252288 25.269529630198974,
55.368054628415855 25.270364015710307,
55.368827104612151 25.270499845366924))', 4326)
SET #polygon = CASE
WHEN #polygon.STArea() > #polygon.ReorientObject().STArea()
THEN #polygon.ReorientObject()
ELSE #polygon
END
SELECT #polygon
(You may also wish to do a plain SELECT #polygon before the CASE to see what the original looked like)
However, take careful note of what the above assumption means - if your users may wish to provide "the whole planet minus this small area around 55 degrees East/25 degrees North", there's now no way for you to accept such a value.
References - STArea ReorientObject

Getting multiple values from same xml column in SQL Server

I want to get the values from same xml node under same element.
Sample data:
I have to select all <award_number> values.
This is my SQL code:
DECLARE #xml XML;
DECLARE #filePath varchar(max);
SET #filePath = '<workFlowMeta><fundgroup><funder><award_number>0710564</award_number><award_number>1106058</award_number><award_number>1304977</award_number><award_number>1407404</award_number></funder></fundgroup></workFlowMeta>'
SET #xml = CAST(#filePath AS XML);
SELECT
REPLACE(Element.value('award_number','NVARCHAR(255)'), CHAR(10), '') AS award_num
FROM
#xml.nodes('workFlowMeta/fundgroup/funder') Datalist(Element);
Can't change this #xml.nodes('workFlowMeta/fundgroup/funder'), because I'm getting multiple node values inside funder node.
Can anyone please help me?
Since those <award_number> nodes are inside the <funder> nodes, and there could be several <funder> nodes (if I understood your question correctly), you need to use two .nodes() calls like this:
SELECT
XC.value('.', 'int')
FROM
#xml.nodes('/workFlowMeta/fundgroup/funder') Datalist(Element)
CROSS APPLY
Element.nodes('award_number') AS XT(XC)
The first .nodes() call gets all <funder> elements, and then the second call goes into each <funder> element to get all <award_number> nodes inside of that element and outputs the value of the <award_number> element as a INT (I couldn't quite understand what you're trying to do to the <award_number> value in your code sample....)
Your own code was very close, but
You are diving one level to low
You need to set a singleton XPath for .value(). In most cases this means a [1] at the end)
As you want to read many <award_number> elements, this is the level you have to step down in .nodes(). Reading these element's values is easy, once you have your hands on it:
SELECT
REPLACE(Element.value('text()[1]','NVARCHAR(255)'), CHAR(10), '') AS award_num
FROM
#xml.nodes('/workFlowMeta/fundgroup/funder/award_number') Datalist(Element);
What are you trying to do with the REPLACE()?
If all <arward_number> elements contain valid numbers, you should use int or bigint as target type and there shouldn't be any need to replace non-numeric characters. Try it like this:
SELECT Element.value('text()[1]','int') AS award_num
FROM #xml.nodes('/workFlowMeta/fundgroup/funder/award_number') Datalist(Element);
If marc_s is correct...
... and you have to deal with several <funder> groups, each of which contains several <award_number> nodes, go with his approach (two calls to .nodes())

Get geometry from a varchar(max) in an update query

I've got a table full of WKT (well known text) in a varchar(max) column. This is formatted exactly as geometry. So, for example, one of the values is:
POLYGON ((174.893529167059 -37.0260462162965,174.89351593407 -37.0260221329151,174.893508034056 -37.0260077002766,174.893444415879 -37.0258916500588,174.893416916056 -37.0258414997842,174.893481733297 -37.0258186834198,174.893492016755 -37.0258150663863,174.89349653254 -37.025823316032,174.893512415978 -37.0258522827285,174.893556883897 -37.0259333832477,174.893591032956 -37.0259956661343,174.893604265986 -37.0260197504078,174.893575149738 -37.0260300006258,174.893529167059 -37.0260462162965))
However, I need to convert this varchar(max) field into a geometry field. Unfortunately, SQL Server needs to have some other information in order to do this, so I can't just change the type of the field from varchar(max) to geometry.
I've created a blank geometry column in the same table (MyGeometry) but I'm failing in trying to convert it. Here is my code (where 2193 is the CRS I'm dealing with). WKT is my varchar(max) field and MyGeometry is my new geometry field.
UPDATE MY_TABLE
SET MyGeometry = geometry::STPolyFromText('' + WKT + '', 2193)
EDIT - currently coming back saying the WKT is not valid (System.FormatException 24111 - the input isn't valid).
Which is strange as it matches up perfectly with some other inputs I have in how it's styled.
This will do :
UPDATE MY_TABLE
SET MyGeometry = geometry::STGeomFromText('POLYGON ((174.893529167059 -37.0260462162965,174.89351593407 -37.0260221329151,174.893508034056 -37.0260077002766,174.893444415879 -37.0258916500588,174.893416916056 -37.0258414997842,174.893481733297 -37.0258186834198,174.893492016755 -37.0258150663863,174.89349653254 -37.025823316032,174.893512415978 -37.0258522827285,174.893556883897 -37.0259333832477,174.893591032956 -37.0259956661343,174.893604265986 -37.0260197504078,174.893575149738 -37.0260300006258,174.893529167059 -37.0260462162965))', 0)
You can change that 'POLYGON....' to your VARCHAR(MAX) field.
0 at the end, which is SRID only relevant if you're using Geography.
You can also try :-
UPDATE MY_TABLE SET MyGeometry = GEOMETRY::STGeomFromText('POLYGON ((174.893529167059 -37.0260462162965,174.89351593407 -37.0260221329151,174.893508034056 -37.0260077002766,174.893444415879 -37.0258916500588,174.893416916056 -37.0258414997842,174.893481733297 -37.0258186834198,174.893492016755 -37.0258150663863,174.89349653254 -37.025823316032,174.893512415978 -37.0258522827285,174.893556883897 -37.0259333832477,174.893591032956 -37.0259956661343,174.893604265986 -37.0260197504078,174.893575149738 -37.0260300006258,174.893529167059 -37.0260462162965))',4326);
The value of SRID passed should be 4326 and not 0
You can check the URL below. I found this information in another similar question (older post) so pasting it without any changes
I found solution, SQL Server Spatial Tools
http://sqlspatialtools.codeplex.com/
Followings are the methods solved my problem.
IsValidGeographyFromText(string inputWKT, int srid)
Check if an input WKT can represent a valid geography. This function requires that the WTK coordinate values are longitude/latitude values, in that order and that a valid geography SRID value is supplied. This function will not throw an exception even in edge conditions (i.e. longitude/latitude coordinates are reversed to latitude/longitude).
SqlGeography MakeValidGeographyFromText(string inputWKT, int srid)
Convert an input WKT to a valid geography instance. This function requires that the WKT coordinate values are longitude/latitude values, in that order and that a valid geography SRID value is supplied.

SQL Server 2008 Geometry not working?

I'm having an issue with SQL Server 2008 and the geometry functions. I'm trying to create non-overlapping shapes using the STDifference function... but it does not seem to be working 100% of the time.
Here is all the sample code to demonstrate the issue. Anybody have any idea to make these non-overlapping polygons? (except "don't make your polygons so complex")
-- create our Geometry polygons.
DECLARE #Geo1 Geometry, #Geo2 Geometry;
SET #Geo1 = geometry::STGeomFromText('POLYGON ((-79725887.5234375 42951274.765625, -79699548.921875 42991827.84375, -79695546.375697568 42997990.498925969, -79695559.967852488 42998690.733179785, -79696152.0625 43029192.375, -79715247.75 43051708.75, -79802181.8984375 43020797.71875, -79806253.6640625 43018621.6953125, -79810436.03125 43014767.046875, -79825837.5 43000572.375, -79830640.625 42973672.03125, -79832936.7265625 42960812.4296875, -79725887.5234375 42951274.765625))',0);
SET #Geo2 = geometry::STGeomFromText('POLYGON ((-79863430.6875 42937209.4375, -79850399.0625 42940068.75, -79850394.9375 42940069.625, -79845320.6875 42946082.625, -79843216.25 42948576.375, -79832949.125 42960743, -79814909.939453125 43061773.556640625, -79817218.30078125 43060262.947265625, -79823496.6875 43056154.3125, -79867800.5 43027161.5625, -79871834.50390625 43024521.70703125, -79875660.228515625 43022018.123046875, -79875666.8125 43022013.8125, -79875674.536313191 43022008.760254942, -79875676.408203125 43022007.53515625, -79875677.236328125 43022006.994140625, -79875718.458984375 43021980.017578125, -79875728.506891936 43021973.442301653, -79881723.017578125 43018050.58984375, -79882437.0625 43017583.3125, -79882585.375 43017486.25, -79884466.9375 43016254.9375, -79884550.875 43016200, -79886514.3125 43014915.125, -79887785.5 43014083.25, -79887790.4375 43014080, -79887793.125 43014078.26953125, -79887807.171875 43014069.076171875, -79887825.568359375 43014057.03515625, -79887831.322335 43014053.269705132, -79888029.5 43013923.5625, -79890094.5625 43012572.1875, -79934236.875 42983685.125, -79863430.6875 42937209.4375))',0);
-- A quick test so you can see them
SELECT #Geo1, 'Geo1' as MyName UNION ALL SELECT #Geo2, 'Geo2' as MyName;
-- how do they compare initially?
SELECT
#Geo1.STTouches(#Geo2) as 'Touches'
,#Geo1.STOverlaps(#Geo2) as 'Overlaps'
,#Geo1.STIntersects(#Geo2) as 'Intersects'
-- try to make them NOT overlap or intersect
SET #Geo1 = #Geo1.STDifference(#Geo2);
SET #Geo2 = #Geo2.STDifference(#Geo1);
-- Now, how do they compare?
SELECT
#Geo1.STTouches(#Geo2) as 'Touches'
,#Geo1.STOverlaps(#Geo2) as 'Overlaps'
,#Geo1.STIntersects(#Geo2) as 'Intersects'
-- what does the intersection look like?
SELECT #Geo1.STIntersection(#Geo2).STAsText();
This is the final select result:
MULTIPOLYGON (((-79831832.015625 42966999.5078125, -79830502.34765625 42974446.45703125, -79830181.430394545 42976243.79133676, -79830220.96484375 42976022.375, -79831832.015625 42966999.5078125)), ((-79832481.0538819 42963364.484146826, -79832328.75390625 42964217.45703125, -79831832.015625 42966999.5078125, -79832481.0538819 42963364.484146826)))
Not an answer, just an observation... I get different results if I introduce two new variables for the two differences.
-- create our Geometry polygons.
DECLARE #Geo1 Geometry, #Geo2 Geometry, #Geo3 Geometry, #Geo4 Geometry;
SET #Geo1 = geometry::STGeomFromText('POLYGON ((-79725887.5234375 42951274.765625, -79699548.921875 42991827.84375, -79695546.375697568 42997990.498925969, -79695559.967852488 42998690.733179785, -79696152.0625 43029192.375, -79715247.75 43051708.75, -79802181.8984375 43020797.71875, -79806253.6640625 43018621.6953125, -79810436.03125 43014767.046875, -79825837.5 43000572.375, -79830640.625 42973672.03125, -79832936.7265625 42960812.4296875, -79725887.5234375 42951274.765625))',0);
SET #Geo2 = geometry::STGeomFromText('POLYGON ((-79863430.6875 42937209.4375, -79850399.0625 42940068.75, -79850394.9375 42940069.625, -79845320.6875 42946082.625, -79843216.25 42948576.375, -79832949.125 42960743, -79814909.939453125 43061773.556640625, -79817218.30078125 43060262.947265625, -79823496.6875 43056154.3125, -79867800.5 43027161.5625, -79871834.50390625 43024521.70703125, -79875660.228515625 43022018.123046875, -79875666.8125 43022013.8125, -79875674.536313191 43022008.760254942, -79875676.408203125 43022007.53515625, -79875677.236328125 43022006.994140625, -79875718.458984375 43021980.017578125, -79875728.506891936 43021973.442301653, -79881723.017578125 43018050.58984375, -79882437.0625 43017583.3125, -79882585.375 43017486.25, -79884466.9375 43016254.9375, -79884550.875 43016200, -79886514.3125 43014915.125, -79887785.5 43014083.25, -79887790.4375 43014080, -79887793.125 43014078.26953125, -79887807.171875 43014069.076171875, -79887825.568359375 43014057.03515625, -79887831.322335 43014053.269705132, -79888029.5 43013923.5625, -79890094.5625 43012572.1875, -79934236.875 42983685.125, -79863430.6875 42937209.4375))',0);
-- A quick test so you can see them
SELECT #Geo1, 'Geo1' as MyName UNION ALL SELECT #Geo2, 'Geo2' as MyName;
-- how do they compare initially?
SELECT
#Geo1.STTouches(#Geo2) as 'Touches'
,#Geo1.STOverlaps(#Geo2) as 'Overlaps'
,#Geo1.STIntersects(#Geo2) as 'Intersects'
-- try to make them NOT overlap or intersect
SET #Geo3 = #Geo1.STDifference(#Geo2);
SET #Geo4 = #Geo2.STDifference(#Geo1);
-- Now, how do they compare?
SELECT
#Geo3.STTouches(#Geo4) as 'Touches'
,#Geo3.STOverlaps(#Geo4) as 'Overlaps'
,#Geo3.STIntersects(#Geo4) as 'Intersects'
-- what does the intersection look like?
SELECT #Geo3.STIntersection(#Geo4).STAsText();
Compare:
Touches Overlaps Intersects
1 0 1
Final Select:
MULTIPOINT ((-79830220.96484375 42976022.375), (-79831832.015625 42966999.5078125))
I suspect this is due to the method/precision with which SQL Server performs spatial calculations. For operations like STIntersection() etc, SQL Server rounds the supplied float coordinate values to a 27 bit integer grid. This can introduce slight distortions to the coordinates returned as the result of spatial operations.
In your case, your coordinate values are large, which means that the fixed size integer grid must be made quite coarse to accommodate the full range of data. The relative difference between the intersecting coordinates that you're trying to remove, however, is very small. When snapped to this coarse grid, SQL Server is unable to correctly identify the area of intersection.
See here for a explanation, and also a suggestion that this situation has been improved in SQL Server Denali:
https://connect.microsoft.com/SQLServer/feedback/details/580254/spatial-operations-are-done-with-a-low-precision-causing-troubles-in-the-returned-data
As pointed out by Joe Stefanelli, your polygons don't technically overlap but they do intersect. The reason is that if you cut a hole out of one polygon using a smaller polygon, the smaller polygon will not overlap the new polygon but it will intersect it along the edge of the cut. It isn't like a table saw that removes some material along the edge of the cut. I could not include the code because SO is having a problem with certain SQL statements and blocks the post.
SEE REFERENCE A in image
If you would like it not to overlap OR intersect, you can create your own sawblade effect. Apply a very small buffer around the smaller of the geometries when using it in the STDifference() function.
SEE REFERENCE B in image
I know this post is old but it does seem pertinent still for those of us who will still be on 2008 for a while.

Resources