I'm trying to implement a function that returns all entries of my table that contains polygons (that describe areas) within a specific radius (distance). I found the function SDO_GEOM.SDO_WITHIN_DISTANCE and read this post.
Since this is a theoretical approach and I have no real data - and I'm not a native speaker, I'm not sure at all if this function is able to do that.
First of all, you need to use the SDO_WITHIN_DISTANCE operator, not the SDO_GEOM.WITHIN_DISTANCE function. The first will perform a search using the spatial index on the polygons table. The second will not (and so will be very slow).
Then SDO_WITHIN_DISTANCE may or may not be what you need, depending on the way you define "within a radius". If by that you mean that the closest border of a polygon must be within the radius, then SDO_WITHIN_DISTANCE is what you need.
Let's assume you have a table AREAS (ID, GEOMETRY) and a table LOCATIONS (ID, GEOMETRY) and you want to find all areas within 10 km of point 42:
select a.id
from areas a, locations l
where l.id=42
and sdo_within_distance (a.geometry, l.geometry, 'distance=10 unit=km') = 'TRUE';
On the other hand, if you want to find polygons that are completely contained within the radius, then you need to construct a buffer of 10 km and use that as a search area to find the matching polygons:
select a.id
from areas a, locations l
where l.id=42
and sdo_inside (
a.geometry,
sdo_geom.sdo_buffer (
l.geometry,
10,
0.05,
'unit=km'
)
) = 'TRUE';
It's possible to use SDO_GEOM.SDO_WITHIN_DISTANCE in a WHERE clause to do what you want - i.e. restrict the rows based on their distance from an origin shape.
Related
I have two indexes with geo shape, One is containing some polygons/multipolygons (wkb). And another is containing some points(wkb).
Let's consider the following documents,
Index(A)=[ # A is polygon's index
{"geom_name": "Dhaka", "geom_type":"city",
"geom": "POLYGON((90.35087585449219 23.87767555995429,90.3529357910 ...))","id":"id1"},
{"geom_name": "Chattogram", "geom_type":"city",
"geom": "POLYGON((91.35087585449219 23.87767555995429,92.3529357910 ...))","id":"id2"},...]
Index(B)={"address": "deul, savar", "geom_type":"address",
"geom": "POINT(90.35087585449219 23.87767555995429)","id":"p1"...},
Now, I have the id of a single polygon and I want to get those points (if possible) or the count of points which lies (point in polygon) in that polygon.
What will be the query to get those points or size in that particular polygon?
I have an entity called Shop which has a DBGeorgpraphy column called Position
A sample shop in the database has a Position value of POINT (145.034242 -37.825519)
I am trying to retrieve all shops that fall within a polygon.
var polygon = DbGeography.PolygonFromText(#"POLYGON((145.2898592378906 -37.66376896413059,
145.2898592378906 -37.93504877166811,
144.7075838472656 -37.93504877166811,
144.7075838472656 -37.66376896413059,
145.2898592378906 -37.66376896413059))",
4326);
var shops = db.Shops.Where(p => p.Position.Intersects(polygon));
I would expect the sample shop to be included in the results but it doesn't. Can anyone enlighten me?
The answer is to construct the polygon in the opposite direction, i.e. anti-clockwise.
var polygon = DbGeography.PolygonFromText(#"POLYGON((145.2898592378906 -37.66376896413059,
144.7075838472656 -37.66376896413059,
144.7075838472656 -37.93504877166811,
145.2898592378906 -37.93504877166811,
145.2898592378906 -37.66376896413059))",
4326);
I'm drawing several heatmaps using the image() function in R.
The sizes of the heatmaps are quite variable, so every heatmap has a different height, however I want the row heights be uniform across heatmaps.
So I create heatmaps from these two matrices, and the heights of each cell are different between two heatmaps:
m1<-replicate(40, rnorm(20))
image(1:ncol(m1), 1:nrow(m1), t(m1), axes = FALSE,xlab="",ylab="")
m2<-replicate(40, rnorm(10))
image(1:ncol(m2), 1:nrow(m2), t(m2), axes = FALSE,xlab="",ylab="")
For the life of me, I can't figure out how can I specify the row height. It must be a very easy fix, but I can't figure it out.
You give very limited information. E.g., do you want to create PDFs? Or place several plots on one page?
Here is one solution:
par(fin=c(5,5),mar=c(0,0,0,0))
image(1:ncol(m1), 1:nrow(m1), t(m1), axes = FALSE,xlab="",ylab="")
par(fin=c(5,2.5),mar=c(0,0,0,0))
image(1:ncol(m2), 1:nrow(m2), t(m2), axes = FALSE,xlab="",ylab="")
I am sure there are more elegant solutions depending on what you actually want to do with the graphs.
Just set a common maximum number of rows for all the heatmaps using the ylim parameter:
m1<-replicate(40, rnorm(20))
m2<-replicate(40, rnorm(10))
image(1:ncol(m1), 1:nrow(m1), t(m1), axes=FALSE, ann=FALSE, ylim=c(0, max(sapply(list(m1,m2),nrow)) ))
image(1:ncol(m2), 1:nrow(m2), t(m2), axes=FALSE, ann=FALSE, ylim=c(0, max(sapply(list(m1,m2),nrow)) ))
You may want to manually specify the ylim argument and have that be the same between the 2 plots:
par(mfrow=c(1,2))
image( 0:ncol(m1), 0:nrow(m1), t(m1), axes=FALSE, xlab='', ylab='',
ylim=c(0,nrow(m1)) )
image( 0:ncol(m2), 0:nrow(m2), t(m2), axes=FALSE, xlab='', ylab='',
ylim=c(0,nrow(m1)) )
I used connected component labeling algorithm (bwconncomp) to label the different parts of a binary image (MATLAB). Now i need to calculate the area of different labels and remove the labels with smaller area. Can i use the default area finding command or is there any specific commands for that in matlab...Help..
From the documentation:
CC = bwconncomp(BW) returns the connected components CC found in BW.
The binary image BW can have any dimension. CC is a structure with
four fields...
The final field in CC is PixelIdxList, which is:
[a] 1-by-NumObjects cell array where the kth element in the cell array is
a vector containing the linear indices of the pixels in the kth object.
You can find the area of each label by looking at the length of the corresponding entry in the cell array. Something like:
areas_in_pixels = cellfun(#length, CC.PixelIdxList);
The PixelIdxList is a cell array, each member of which contains the linear indexes of the pixels present in that connected component. The line of code above finds the length of each cell in the cell array - i.e. the number of pixels in each connected component.
I've used cellfun to keep the code short and efficient. A different way of writing the same thing would be something like:
areas_in_pixels = nan(1, length(CC.PixelIdxList);
for i = 1:length(CC.PixelIdxList)
areas_in_pixels(i) = length(CC.PixelIdxList{i});
end
For each connected component, you can then find the size of that component in pixels by accessing an element in areas_in_pixels:
areas_in_pixels(34) %# area of connected component number 34
If you don't want to write lots of code like above just use built-in functions of MATLAB to detect the area. Label your components and from the properties of the component you can find out the area of that component. Suppose Bw is the binary image:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
for k = 1:length(B)
area(k)=stats.Area;
end
You can make this better still by avoiding the for loop with the following:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
area = [stats.Area];
Best,
-Will
I extracted country outline data from somewhere and successfully managed to convert it into an array of lat-lng coordinates that I can feed to Google maps API to draw polyline or polygons.
The problem is that that there are about 1200+ points in that shape. It renders perfectly in Google maps but I need to reduce the number of points from 1200 to less than 100. I don't need a very smooth outline, i just need to throw away the points that I can live without. Any algorithm or an online tool that can help me reduce the number of points is needed.
Found this simple javascript by Bill Chadwick. Just feed in the LatLng to an array and pass in to the source arguments in a function here Douglas Peucker line simplification routine
it will output an array with less points for polygon.
var ArrayforPolygontoUse= GDouglasPeucker(theArrayofLatLng,2000)
var polygon=new google.maps.Polygon({
path:ArrayforPolygontoUse,
geodesic:true,
strokeColor:"#0000FF",
strokeOpacity:0.8,
strokeWeight:2,
fillColor:"#0000FF",
fillOpacity:0.4,
editable:true
});
theArrayofLatLng is an array of latlng that you collected using google maps api.
The 2000 value is kink in metres. My assumption is, the higher the value, more points will be deleted as an output.
For real beginners:
Make sure you declare the js file on your html page before using it. :)
<script type="text/javascript" src="js/GDouglasPeucker.js"></script>
I think MapShaper can do this online
Otherwise, implement some algorithm
If you can install postgis which i think is easy as they provide an installer then you can import the data and execute snaptogrid() or st_simplify() for which i cannot find an equivalent in mysql.If you decide to go with postgis which i recommend cause it will help you down the road i can provide you with the details.
Now for an easy custom solution you can reduce size by cutting or rounding some of the last digits of the coords and then merge the same coords resulting actually in a simple snaptogrid().
Hope it helps
I was looking for exactly the same thing and found Simplify.js. It does exactly what you want and is incredibly easy to use. You simply pass in your coordinates and it will remove all excess points.
simplify(points, tolerance, highQuality)
The points argument should contain an array of your coordinates formatted as {x: 123, y: 123}. (Afterwards you can convert it back to the format you wish.)
The tolerance should be the precision in decimal degrees. E.g. 0.0001 for 11 meters. Increasing this number will reduce the output size.
Set highQuality to true for better results if you don't mind waiting a few milliseconds longer.
Mostly likely what you want to divide the points into 2 half and want to try my Javascript function:
function shortenAndShow ( polyline, color ) {
var dist = 0, copyPoints = Array ( );
for ( var n = 0, var end = polyline.getVertexCount ( ) - 1; n < end ; n++ ) {
dist += polyline.getVertex ( n ).distanceFrom ( polyline.getVertex ( n +1 ) );
copyPoints.push ( polyline.getVertex (n) );
}
var lastPoint = copyPoints [copyPoints.length-1];
var newLine = new GPolyline (copyPoints, color, 2, 1);
gmap2.addOverlay ( newLine );
}
I agree the Unreason's anwser,The website support GeoJson,I used it in my website,and it cut down my geoJson ,But I think you also need this world country geo Json