Work with coordinates with altitude and accuracy in PostgreSQL + Postgis - postgresql

In PostgreSQL, I have a table with three columns, one for points, one for lines and one for polygons, obtained from Kobotoolbox. The data is written like this:
Point: Latitude Longitude Altitude Accuracy
Line: Latitude Longitude Altitude Accuracy; Latitude Longitude Altitude Accuracy
Polygon: Latitude Longitude Altitude Accuracy; Latitude Longitude Altitude Accuracy; Latitude Longitude Altitude Accuracy
How can I transform them into points, lines and polygons that I can use later in other operations?
A sample of the data:
CREATE TABLE data_test (point text,line text, polygon text);
insert into data_test VALUES
('12.126441 -86.298396 0 0', '12.125673 -86.297157 0 0;12.125367 -86.299428 0 0;12.125839 -86.299374 0 0;12.126174 -86.299063 0 0;12.126877 -86.298322 0 0;12.126867 -86.297936 0 0;12.126835 -86.29727 0 0;12.125673 -86.297157 0 0', '12.12614 -86.299082 0 0;12.126392 -86.29885 0 0;12.126544 -86.298705 0 0;12.126429 -86.29842 0 0;12.12645 -86.298276 0 0;12.126471 -86.298125 0 0;12.126492 -86.298007 0 0'),
('13.665354 -89.278524 0 0', '13.666044 -89.278656 0 0;13.666023 -89.278065 0 0;13.666138 -89.278049 0 0;13.666326 -89.278097 0 0;13.666264 -89.278282 0 0;13.666364 -89.278314 0 0;13.666435 -89.278205 0 0;13.666607 -89.278124 0 0;13.666904 -89.278028 0 0;13.66717 -89.27806 0 0;13.66717 -89.278226 0 0;13.666951 -89.278248 0 0;13.666555 -89.278656 0 0;13.666044 -89.278656 0 0', '13.665354 -89.278524 0 0;13.665358 -89.278663 0 0;13.665373 -89.278902 0 0;13.665368 -89.279106 0 0;13.665368 -89.279299 0 0;13.665769 -89.279299 0 0;13.666113 -89.279289 0 0;13.666129 -89.279047 0 0;13.666108 -89.278779 0 0;13.666103 -89.278618 0 0'),
('-31.635851 -60.774175 0 0', '-31.635975 -60.774324 0 0;-31.63602 -60.773981 0 0;-31.636074 -60.774321 0 0;-31.635975 -60.774324 0 0', '-31.635863 -60.774313 0 0;-31.636091 -60.774325 0 0'),
('-24.840938 -65.435611 1202 0', '-24.833342 -65.437115 0 0;-24.832563 -65.435223 0 0;-24.832398 -65.433348 0 0;-24.833268 -65.432525 0 0;-24.834146 -65.432114 0 0;-24.835607 -65.432157 0 0;-24.837437 -65.435485 0 0;-24.838197 -65.436709 0 0;-24.834891 -65.438848 0 0;-24.833411 -65.438289 0 0;-24.833342 -65.437115 0 0', '-24.841016 -65.435613 0 0;-24.840587 -65.436 0 0;-24.840062 -65.435142 0 0;-24.839463 -65.435598 0 0;-24.838046 -65.436552 0 0;-24.837121 -65.436216 0 0'),
('13.664852 -89.278977 904.1 13.1899244', '13.677341 -89.283306 0 0;13.677091 -89.279078 0 0;13.675131 -89.27912 0 0;13.675069 -89.280215 0 0;13.674485 -89.280279 0 0;13.674698 -89.283357 0 0;13.677341 -89.283306 0 0', '13.664924 -89.278894 0 12.244;13.66493 -89.279219 0 0;13.665451 -89.279219 0 0;13.665446 -89.279326 0 0;13.666176 -89.279312 0 0;13.666171 -89.282736 0 0;13.672801 -89.282456 0 0;13.672885 -89.283684 0 0;13.676304 -89.283392 0 0;13.676179 -89.282139 0 0'),
('1.331093 -75.974085 300 3', '1.644977 -76.231295 0 0;1.638842 -76.057188 0 0;1.515293 -75.961053 0 0;1.485091 -76.079262 0 0;1.380753 -76.189193 0 0;1.290141 -76.252404 0 0;1.229731 -76.312859 0 0;1.259936 -76.463997 0 0;1.408211 -76.48044 0 0;1.493328 -76.395238 0 0;1.567459 -76.321034 0 0;1.644977 -76.231295 0 0', '1.331994 -75.972156 0 0;1.407503 -75.990544 0 0'),
('14.595962 -90.530973 0 0', '14.596218 -90.530673 0 0;14.596291 -90.531027 0 0;14.595829 -90.53121 0 0;14.595699 -90.530839 0 0;14.596218 -90.530673 0 0', '14.599893 -90.535245 0 4107.503292443888;14.600378 -90.535292 0 0;14.60045 -90.53526 0 0;14.600414 -90.535061 0 0;14.60003 -90.533814 0 0;14.600336 -90.533334 0 0;14.600352 -90.53454 0 0;14.598493 -90.530363 0 0;14.599376 -90.532509 0 0;14.596479 -90.530738 0 0'),
('13.664776 -89.278983 0 0', '13.665024 -89.27906 0 0;13.66492 -89.278969 0 0;13.664933 -89.27887 0 0;13.665006 -89.278946 0 0;13.665024 -89.27906 0 0', '13.664933 -89.279011 0 14.404;13.664933 -89.279011 0 14.404'),
('1.328949 -75.9738 360 13.166', '1.328949 -75.9738 0 13.166;1.328871 -75.973761 0 0;1.328812 -75.973638 0 0;1.328726 -75.97374 0 0;1.328721 -75.973826 0 0;1.328949 -75.9738 0 13.166', '1.328949 -75.9738 0 13.166;1.328955 -75.973801 0 12.265;1.328642 -75.973665 0 0;1.328653 -75.973778 0 0;1.328706 -75.973826 0 0;1.328803 -75.973858 0 0;1.328915 -75.973761 360 0'),
('13.780375 -89.117772 0 0', '13.780312 -89.118426 0 0;13.780208 -89.117739 0 0;13.779521 -89.117859 0 0;13.779635 -89.118496 0 0;13.780312 -89.118426 0 0', '13.780079 -89.11995 0 0;13.779855 -89.119965 0 0;13.779594 -89.118274 0 0'),
('14.595925 -90.53099 0 0', '14.595711 -90.531217 0 0;14.595564 -90.530912 0 0;14.596266 -90.530738 0 0;14.59628 -90.531038 0 0;14.595711 -90.531217 0 0', '14.596188 -90.530608 0 0;14.596318 -90.530668 0 0;14.596365 -90.530759 0 0;14.596391 -90.531006 0 0;14.596303 -90.531059 0 0;14.59611 -90.531016 0 0;14.596001 -90.530947 0 0;14.596017 -90.530818 0 0'),
('13.664903 -89.279061 904 1', '13.667471 -89.284878 0 0;13.667815 -89.284812 0 0;13.667655 -89.281555 0 0;13.667315 -89.281592 0 0;13.667471 -89.284878 0 0', '13.664972 -89.279136 0 0;13.665233 -89.279351 0 0;13.666119 -89.279307 0 0;13.666233 -89.281576 0 0;13.667307 -89.281563 0 0');`
I looked in the Postgis documentation and I can't figure out how to operate with this data. It is not necessary to keep the accuracy of each node, but I would like to keep the altitude. Any help please?

You can use st_geomFromText after replacing ; with ,, and after specifying the geometry type. Since the data is expressed as lat/long, you must also swap the coordinates.
select st_AsText(ST_FlipCoordinates(st_geomfromText('POINT(12.126441 -86.298396 0 0)')));
select st_AsText(ST_FlipCoordinates(st_geomfromText('POLYGON((' || replace('12.125673 -86.297157 0 0;12.125367 -86.299428 0 0;12.125839 -86.299374 0 0;12.126174 -86.299063 0 0;12.126877 -86.298322 0 0;12.126867 -86.297936 0 0;12.126835 -86.29727 0 0;12.125673 -86.297157 0 0))',';',','))));
Or directly from a table:
SELECT ST_FlipCoordinates(ST_GeomFromText('POINT(' || point_txt_column || ')')),
ST_FlipCoordinates(ST_GeomFromText('LINESTRING(' || line_txt_column || ')')),
ST_FlipCoordinates(ST_GeomFromText('POLYGON((' || replace(polygon_txt_column,';',',') || '))'))
FROM myTable;
PS: from the sample data, it seems you have swapped the line and polygon data, as the last point of a polygon must be the same as its first point.

Related

How to draw 2 merging trees using an adjacency matrix in Matlab

I have an adjacency matrix describing two trees that merges in the middle. An exemple for 10 nodes:
The corresponding adjacency matrix is a 10x10 matrix where the first row correspond to the first node (start of the first tree, node #1) and the last row to the root of the second tree (end of the second tree, node #10).
Here is the adjacency matrix corresponding to a larger example with 22 nodes:
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
I'm trying to plot this adjacency matrix as the picture showed above using Matlab. Matlab as some tools for plotting trees, for example the code given in:
https://blogs.mathworks.com/cleve/2017/03/20/morse-code-binary-trees-and-graphs/
However, using the previous matrix (let's label it 'A') and the following code:
G = digraph(A);
Gp = plot(G);
does not produce a tree, but a graph (not ordered as a tree).
Thus, how to produce a picture of a tree (as showed above) using 'A' in Matlab?
Please note that I also have matrices describing trees where the degree between the children nodes are 3 (or more) rather than 2.
Zero-out half of your adjacency matrix to make the connection one-way.
By default, MATLAB tries to decide the layout of graphs automatically, based on the structure of your graph. There are a few different graph layouts you can choose from.
The option you wanted is the 'Layered' layout; but I tested it with your example, and it definitely still doesn't look like a tree. The reason being that your adjacency matrix is symmetrical, and the connection is two-way. This confuses MATLAB when placing the nodes, and it doesn't think it's a tree.
The easy fix, is you can zero-out the lower triangular half of your adjacency matrix. I used the function tril for this.
% Create a lower triangular matrix with the dimension of A,
idx = tril(ones(size(A)));
% Make it a logical array to select matrix elements with
idx = logical(idx);
% Select the defined lower triangular part, and set that to zero
A(idx) = 0;
% Generate-Plot graph as you did
G = digraph(A);
plot(G)
Result

How to correctly use the col2im function?

This function is confusing to use, and it always gives me an error:
To RESHAPE the number of elements must not change.
That's my code:
im=im2col(zeros(300,300),[3 3]);
im(:,9)=ones(9,1);
im=col2im(im,[3 3],[300 300]);
Basically, this code just gets the block at index 6, replaces it with ones, and reassembles it back into the original image. What's wrong with this code?
It seems you want to create distinct blocks from your input array, change single blocks, and rearrange them. (Your target size is the same as your input array size.) So, you must use the distinct parameter in both, im2col as well as col2im:
blk_size = [3, 3];
im = zeros(9, 9)
temp = im2col(im, blk_size, 'distinct');
temp(:, 3) = ones(prod(blk_size), 1);
im2 = col2im(temp, [3 3], size(im), 'distinct')
Output:
im =
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
im2 =
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0
When using im2col with the sliding parameter, which is also the default, if no parameter is set at all, there'll be a lot more columns in the result than can be rearranged to the input array size, cf. the Tips section on im2col.
Hope that helps!

Search a position of pattern in a cell array

I have a cell array as below which contains 17000 such combinations.
'0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1'
'0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0'
'0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0'
'0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0'
'0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0'
'0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0'
'0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0'
I want to search the patterns in an array in a loop. I am interested in the position of that pattern in the cell array using Matlab. I had tried strcmp() function for comparison but it takes lots of time as each pattern is compared with 17000 elements of the cell array.
Is there any fastest method to search a pattern in cell array?
Use bin2dec to convert all entries in the cell array to integers, then convert the search pattern to int as well and search for ints

How to Count Total Number of pixel of padded value used in image(Padded Image)?

I have one binary image so it has only 2 value like 0 and 1. After, I convert this into a padded image of different values, like the image will have curve shape. I took a 3 X 3 matrix of value and if i get curve shape then I padded the image with 1, or any number. I use 15 different types shape values like junction point, end point etc.
After, I give the values 1 to 15 - or the appropriate number according its shape. As such, I am getting an image like:
Figure
0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0
I would like to count how many 1s there are in the image, followed by 2s, 3s, etc. up to 15. For example,
as shown in the figure, if the pad number was 5, the total number of pixels would be 3. If the pad number was 1, the total number of pixels would be 6.
Use histc:
>> im = [ 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 5 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 ]; %// data
>> values = 1:15; %// possible values
>> count = histc(im(:), values)
count =
6 %// number of 1's
0 %// number of 2's, etc
0
0
3
0
0
0
0
0
0
0
0
0
0
Or compute it manually with bsxfun:
>> count = sum(bsxfun(#eq, im(:), values(:).'), 1)
>> count =
6 0 0 0 3 0 0 0 0 0 0 0 0 0 0
I can also suggest using accumarray:
im = [0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 5 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 ]; %// data - borrowed from Luis Mendo
counts = accumarray(im(:) + 1, 1);
counts(1) = []
counts =
6
0
0
0
3
Note we have to offset by 1 as accumarray starts indexing the output array at 1. Because you want to disregard the 0s, I simply take the counts result and remove the first entry. This result agrees with what you are seeking. The first element is how many 1s we have encountered, which is 6. The last element is how many 5s you have encountered, which is 3. Because 5 is the largest number encountered in your image, we can say that all symbols after 5 (6, 7, 8, ..., 15) have a count of 0.

Find out first circle in an image on Matlab (wrt. y-axis)

I'm using Matlab. I have a 2-D Binary image/array. like this
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 1 0 0
0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
I want to find out center of very first white block/Circle with respect to y-axis
Answer of the above image will be.
0 1 0
1 1 1
0 1 0
Anyone who have have a simplest solution for this.
If you are looking for exact matches of the template, you can use a moving filter, one example is:
H=[0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 1 0 0 0 0 0 0;
0 0 0 0 0 1 1 1 0 0 1 0 0;
0 0 1 1 0 0 1 0 0 0 0 0 0;
0 0 0 1 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 1 0 0 0 0 0 0;
0 0 0 0 0 0 1 1 0 0 0 0 0;
0 0 0 0 0 0 1 0 0 0 0 0 0];
b=[0 1 0;
1 1 1;
0 1 0];
C=filter2(b,H, 'same');
[x,y]=find(C==max(max(C)));
x and y are the locations of your template in the order that it appears from the top left corner of your array.
Edit: if you have the Image Processing Toolbox and are looking for a less strict way of finding objects that have a roughly circular shape you can use regionprops with the 'Centroid' and 'Eccentricity' arguments with the bwconncomp function.
ObjectStats=regionprops(bwconncomp(H,4), 'Centroid', 'Eccentricity');
Objects with an 'Eccentricity' of 0 (or close to 0) will be the circles.
idx=find(cell2mat({ObjectStats.Eccentricity})==0); % Change ==0 to <0.2 or something to make it less strict.
ctrs={ObjectStats.Centroid};
>> ctrs{1,idx(1)}
ans =
7 3
Note that in your case, a lone pixel is an object with an eccentricity of 0, it is the smallest 'circle' that you can find. If you need to define a minimum size, use the 'Area' property of regionprops
You can do this with a simple 2 dimensional convolution. It will "overlay" the filter along a larger matrix and multiply the filter by the values it is overlaying. If the product is equal to the sum of the filter, then you know you found a match.
Here is some simple code.
mat = [0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 1 0 0
0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0];
filt = [0 1 0
1 1 1
0 1 0];
[row,col] = find(conv2(mat,filt,'same') == sum(filt(:)))