I need a specific function to get if two linestring overlaps.
e.g.
Linestring 1 is Point (0, 0) : Point (10, 0)
Linestring 2 is Point (0, 0) : Point (3, 0)
In this case I need "true" result because LineString 1 overlaps in different points like 0,0 1,0 2,0 & 3,0. I dont need the common points, I only need if two linestring overlaps or not.
I tried with this function in postgis...
overlaps(buffer(LINESTRING1, 0.001), buffer(LINESTRING2, 0.001))
I create a buffer on both linestrings... but muy problem is some times works better, some times not.
Can you help me please?
Thanks!
It's a matter of understanding the spatial predicate terminology used by the DE-9IM, which isn't always intuitive. You don't want "overlaps", but more likely mean "intersects" (i.e. ST_Intersects).
See JTS TestBuilder to get a better understanding of the spatial predicate meanings for different geometry configurations.
Related
This is more a design question so please bear with me.
I have a system that stores locations consisting of the ID, Longitude and Latitude.
I need to compare the distance between my current location and the locations in the database a only choose ones that are within a certain distance.
I have the formula that calculates the distance between 2 locations based on the long/lat and that works great.
My issue is I may have 10 of thousands of locations in the database and don't want to loop through them all every time I need a list of locations close by.
Not sure what other datapoint I can store with the location to make it so I only have to compare a smaller subset.
Thanks.
As was mentioned in the comments, SQL Server has had support for geospatial since (iirc) SQL 2008. And I know that there is support within .NET for that as well so you should be able to define the data and query it from within your application.
Since the datatype is index-able, k nearest neighbor queries are pretty efficient. There's even a topic in the documentation for that use case. Doing a lift and shift from that page:
DECLARE #g geography = 'POINT(-121.626 47.8315)';
SELECT TOP(7) SpatialLocation.ToString(), City
FROM Person.Address
WHERE SpatialLocation.STDistance(#g) IS NOT NULL
ORDER BY SpatialLocation.STDistance(#g);
If you need all the points within that radius, omit the top clause and change the predicate on STDistance() to something like SpatialLocation.STDistance(#g) < 1000 (the SRID I typically use has meters as the unit of measure, so this would say 'within 1 km').
https://gis.stackexchange.com/ is a good place for in-depth advice on this topic.
A classic approach to quickly locating "nearby" values, is to "grid" the area of interest:
Associate each location with a "grid cell", where each cell is a convenient size. Pick a cell-edge-length such that most cells will hold a small number of values and/or that is similar to the distance range you typically query.
If cell edge is 1 km, and you need locations within 2 km, then get data from 5x5 cells centered at the "target" location.
This is guaranteed to include all data +- 2 km from any location within the central cell.
Apply distance formula to each returned location; some will be beyond 2 km.
I've only done this in memory, not from a DB. I think you add two columns, one for X cell number, other for Y cell number.
With indexes on both of those. So can efficiently get a range of Xs by a range of Ys.
Not sure if a combined "X,Y" index helps or not.
I can calculate the distance between two points using:
SELECT ST_Distance(
ST_GeomFromText('SRID=4326;POINT(54.5972850 -5.930119)')
, ST_GeomFromText('SRID=4326;POINT(54.516827 -5.958130)'),
false);
However, my goal is to create a rough circular zone (this can be square, hexagon, octagon .etc) around each point and then check if the zones overlap.
I am looking at ST_Overlaps as a possible solution but I am not sure how to convert these points into polygons to be compared. My ideal result would be something like:
SELECT ST_Overlaps(
ST_CreateCircularPolygon(geom1, 1000, 6)
ST_CreateCircularPolygon(geom2, 10000, 4)
);
Where:
ST_CreateCircularPolygon(geomerty, metreRadius, numberOfRadialPoints (e.g. 6 creates a hexagonal polygon))
Any guidance would be much appreciated!
You can use the quad_seg parameter of st_buffer to specify the number of segments per quarter of a circle. That is, the total number of segments in the output will be a factor of 4.
To produce a square:
select st_asText(st_buffer(st_geomFromText('Point(10 10)'), 1, 'quad_segs=1'));
st_astext
------------------------------------------------------
POLYGON((11 10,10 9,9 10,9.99999999999999 11,11 10))
(1 row)
Octagon:
select st_asText(st_buffer(st_geomFromText('Point(10 10)'), 1, 'quad_segs=2'));
st_astext
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
POLYGON((11 10,10.7071067811865 9.29289321881345,10 9,9.29289321881345 9.29289321881345,9 10,9.29289321881345 10.7071067811865,9.99999999999999 11,10.7071067811865 10.7071067811866,11 10))
(1 row)
Since you want to work in meters but have unprojected coordinates, you can cast your geometry to geography, apply a buffer in meters and cast back to geometry. Let's note that st_buffer in geography will internally cast to a geometry in UTM, do the buffer, then cast back to geography (a lot of casting, but it's handy!)
That being said, a square is not a circle and it sounds very very wrong to assume otherwise. The orientation of the square is not obvious: should a corner be at the north? or should a segment be facing norht? or should the square be rotated? by how much?
You will save yourself a lot of trouble by using a real circle. In this case, don't use st_buffer at all, nor st_distance but rather st_dwithin which can leverage spatial indexes
I use set of images for image processing in which each image generates unique code (Freeman chain code). The size of array for each image varies. However the value ranges from 0 to 7. For e.g. First image creates array of 3124 elements. Second image creates array of 1800 elements.
Now for further processing, I need a fixed size of those array. So, is there any way to Normalize it ?
There is a reason why you are getting different sized arrays when applying a chain code algorithm to different images. This is because the contours that represent each shape are completely different. For example, the letter C and D will most likely contain chain codes that are of a different length because you are describing a shape as a chain of values from a starting position. The values ranging from 0-7 simply tell you which direction you need to look next given the current position of where you're looking in the shape. Usually, chain codes have the following convention:
3 2 1
4 x 0
5 6 7
0 means to move to the east, 1 means to move north east, 2 means to move north and so on. Therefore, if we had the following contour:
o o x
o
o o o
With the starting position at x, the chain code would be:
4 4 6 6 0 0
Chain codes encode how we should trace the perimeter of an object given a starting position. Now, what you are asking is whether or not we can take two different contours with different shapes and represent them using the same number of values that represent their chain code. You can't because of the varying length of the chain code.
tl;dr
In general, you can't. The different sized arrays mean that the contours that are represented by those chain codes are of different lengths. What you are actually asking is whether or not you can represent two different and unrelated contours / chain codes with the same amount of elements.... and the short answer is no.
What you need to think about is why you want to try and do this? Are you trying to compare the shapes between different contours? If you are, then doing chain codes is not the best way to do that due to how sensitive chain codes are with respect to how the contour changes. Adding the slightest bit of noise would result in an entirely different chain code.
Instead, you should investigate shape similarity measures instead. An authoritative paper by Remco Veltkamp talks about different shape similarity measures for the purposes of shape retrieval. See here: http://www.staff.science.uu.nl/~kreve101/asci/smi2001.pdf . Measures such as the Hausdorff distance, Minkowski distance... or even simple moments are some of the most popular measures that are used.
I have a rather specific spatial search I need to do. Basically, have an object (lets call it obj1) with two locations, lets call them point A and point B.
I then have a collection of objects(lets call each one obj2) each with their own A and B locations.
I want to return the top 10 objects from the collection sorted by:
(distance from obj1 A to obj2A) + (the distance from obj1B to obj2B)
Any ideas?
Thanks,
Nick
Update:
Here's a little more detail on the documents and how I want to compare them.
The domain model:
Listing:
ListingId int
Title string
Price double
Origin Location
Destination Location
Location:
Post / Zipcode string
Latitude decimal
Longitude decimal
What i want to do is take a listing object (not in the database) and compare it with the collection of listings in the database. I want the query to return the top 12 (or x) number of listings sorted by the crow flies distance from the origins plus the crow flies distance from destinations.
I don't care about the distance from origin to destination - only about the distance of origin to origin plus destination to destination.
Basically Im trying to find listings where the starting and ending locations are close.
Please let me know if I can clarify more.
Thanks!
Here is how one would solve such a problem in
mysql 4.1 &
mysql 5.
The link from mysql 4.1 seems quite helpful, esp. the first example, it's pretty much what you are asking about.
But if this is not quite helpful, I guess you'd have to loop and do queries either on obj1 or obj2 against its counterpart table.
From algorithmic perspective, I'd find the center of the bounding box, then picked candidates with increasing radius while I find enough.
Also I just want to remind that crow fly distance over the globe is not Pythagoras distance and different formula must be used:
public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
{
double deltaLat = DegreesToRadians(lat2 - lat1);
double deltaLong = DegreesToRadians(lng2 - lng1);
double a = Math.Pow(Math.Sin(deltaLat / 2), 2) +
Math.Cos(DegreesToRadians(lat1))
* Math.Cos(DegreesToRadians(lat2))
* Math.Pow(Math.Sin(deltaLong / 2), 2);
return earthMeanRadiusMiles * (2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)));
}
Sounds like you're building a rideshare website. :)
The bottom line is that in order to sort your query result by surface distance, you'll need spatial indexing built into the database engine. I think your options here are MySQL with OpenGIS extensions (already mentioned) or PostgreSQL with PostGIS. It looks like it's possible in ravenDB too: http://ravendb.net/documentation/indexes/sptial
But if that's not an option, there's a few other ways. Let's simplify the problem and say you just want to sort your database records by their distance to location A, since you're just doing that twice and summing the result.
The simplest solution is to pull every record from the database and calculate the distance to location A one by one, then sort, in code. Trouble is, you end up doing a lot of redundant computations and pulling down the entire table for every query.
Let's once again simplify and pretend we only care about the Chebyshev (maximum) distance. This will work for narrowing our scope within the db before we get more accurate. We can do a "binary search" for nearby records. We must decide an approximate number of closest records to return; let's say 10. Then we query inside of a square area, let's say 1 degree latitude by 1 degree longitude (that's about 60x60 miles) around the location of interest. Let's say our location of interest is lat,lng=43.5,86.5. Then our db query is SELECT COUNT(*) FROM locations WHERE (lat > 43 AND lat < 44) AND (lng > 86 AND lng < 87). If you have indexes on the lat/lng fields, that should be a fast query.
Our goal is to get just above 10 total results inside the box. Here's where the "binary search" comes in. If we only got 5 results, we double the box area and search again. If we got 100 results, we cut the area in half and search again. If we get 3 results immediately after that, we increase the box area by 50% (instead of 100%) and try again, proceeding until we get close enough to our 10 result target.
Finally we take this manageable set of records and calculate their euclidean distance from the location of interest, and sort, in code.
Good luck!
I do not think that you find a solution directly out of the box.
It'll be much more efficient if you use a bounding sphere instead of a bounding box to specify your object.
http://en.wikipedia.org/wiki/Bounding_sphere
C = ( A + B)/2 and R = distance(A,B) /2
You do not precise how much data you want to compare. And if you want to see the closests or the farthest objects pair.
For both case, I think that you have to encode C coordinate as a path in an octtree if you are using 3D or quadtree if you are using 2D.
http://en.wikipedia.org/wiki/Quadtree
This is a first draft I can add more information if this not enough.
If you are not familiar with 3D start with 2D it easier to start with.
I show your latest add, it seems that your problem is very similar to clash detection algorithm.
I think that if you change the coordinate system of the "end-point" by polar coordinate relative to the "start-point". If you round the radial coordinate to your tolerance (x miles), and order them by this value.
Is there a way to subtract a geometry from another? A kind of reverse STUnion..
The problem I am having is that I need to ensure a shape fits within another (without changing the larger shape). I thought I could use the STIntersection to get the shape thats "in". However, STIntersection is not accurate and produces a shape that can (and does) not equate to the true intersection.
You can easily see this if you then take the STDifference of the original shape.
So , what I would like to do is given two shapes I want to subtract one from the other - e.g. Take the STIntersection and then subtract the STDifference.
Any ideas?
Edit: For now, I have created my intersection from a STBuffer(-1) version of the bigger shape, this should account the mathematical variation of STIntersection with a slight reduction in accuracy. However, I would still love to know if you can subtract a geometry from another..
Just use .STDifference(). No need to intersect first, then subtract the intersection. Just subtract directly.
Did you try STWithin?