Find polygon containing point from lat/lng table - postgresql

I have a table, Regions:
| id | name |
|----|----------|
| 1 | Jersey |
| 2 | Scotland |
...
and a table of RegionPoints (which define the bounding box for each region):
| id | regionid | lat | lng |
|----|----------|-------|-------|
| 1 | 1 | 49.27 | -2.27 |
| 2 | 1 | 49.27 | -1.99 |
| 3 | 1 | 49.15 | -2.27 |
| 4 | 1 | 49.15 | -1.99 |
...
Given a latitude and longitude, I want to find the regions which contain the given point.
From my understanding, I need to aggregate by regionid, then
use ST_ConcaveHull, followed by ST_Contains using the latitude and longitude to query for, however my concern is that with a large number of regions, computing a concave hull for each will be very inefficient.
This is my first time using PostGIS, so a bit stuck.

Yes, computing the concave hull "on the fly" can be inefficient with lots of data.
Also, you won't be able to use a spatial index, as your geometries are built at query time.
Using ST_MakeEnvelope instead of ST_ConcaveHull will mitigate the problem.
However, as JGH suggests, you should store those coordinates as polygons in the Regions table, using ST_MakeEnvelope to create them.
Than build a spatial index and use ST_Contains to get the regions that contains a point.

Related

How do I make a specific query in a PSQL database

I need help with a project. Right now, I have a giant postgreSQL database (~6 million rows, 25 columns) and I need to figure out how to get the following information:
For one specific range for one attribute, "20<np<400":
Find local minimum values in another variable, "itt"
Record whole row of data for that local minimum
Add extra column and add to this the next local maximum of itt
Edit: the attribute are as follows: The database has this schema: id | at | itt | engine_torque | ng | np | fuel_flow | engine_oil_pressure | engine_oil_temp | airspeed | altitude | total_air_temp | weight_on_wheels | p25_p3 | bypass | chip_counter | number_of_flight_counter | number_of_engine_run | run_id | ectm_file_id | aircraft_sn | engine_sn | gas_generator_sn | power_section_sn | tail_number
By 'local minima and maxima' i mean that within a certain range of np, i'm looking for the highest and lowest values of itt in close proximity with respect to time, or "at"
Thanks in advance!!!

SPSS group by rows and concatenate string into one variable

I'm trying to export SPSS metadata to a custom format using SPSS syntax. The dataset with value labels contains one or more labels for the variables.
However, now I want to concatenate the value labels into one string per variable. For example for the variable SEX combine or group the rows F/Female and M/Male into one variable F=Female;M=Male;. I already concatenated the code and labels into a new variable using Compute CodeValueLabel = concat(Code,'=',ValueLabel).
so the starting point for the source dataset is like this:
+--------------+------+----------------+------------------+
| VarName | Code | ValueLabel | CodeValueLabel |
+--------------+------+----------------+------------------+
| SEX | F | Female | F=Female |
| SEX | M | Male | M=Male |
| ICFORM | 1 | Yes | 1=Yes |
| LIMIT_DETECT | 0 | Too low | 0=Too low |
| LIMIT_DETECT | 1 | Normal | 1=Normal |
| LIMIT_DETECT | 2 | Too high | 2=Too high |
| LIMIT_DETECT | 9 | Not applicable | 9=Not applicable |
+--------------+------+----------------+------------------+
The goal is to get a dataset something like this:
+--------------+-------------------------------------------------+
| VarName | group_and_concatenate |
+--------------+-------------------------------------------------+
| SEX | F=Female;M=Male; |
| ICFORM | 1=Yes; |
| LIMIT_DETECT | 0=Too low;1=Normal;2=Too high;9=Not applicable; |
+--------------+-------------------------------------------------+
I tried using CASESTOVARS but that creates separate variables, so several variables not just one single string variable. I'm starting to suspect that I'm running up against the limits of what SPSS can do. Although maybe it's possible using some AGGREGATE or OMS trickery, any ideas on how to do this?
First I recreate your example here to demonstrate on:
data list list/varName CodeValueLabel (2a30).
begin data
"SEX" "F=Female"
"SEX" "M=Male"
"ICFORM" "1=Yes"
"LIMIT_DETECT" "0=Too low"
"LIMIT_DETECT" "1=Normal"
"LIMIT_DETECT" "2=Too high"
"LIMIT_DETECT" "9=Not applicable"
end data.
Now to work:
* sorting to make sure all labels are bunched together.
sort cases by varName CodeValueLabel.
string combineall (a300).
* adding ";" .
compute combineall=concat(rtrim(CodeValueLabel), ";").
* if this is the same varname as last row, attach the two together.
if $casenum>1 and varName=lag(varName)
combineall=concat(rtrim(lag(combineall)), " ", rtrim(combineall)).
exe.
*now to select only relevant lines - first I identify them.
match files /file=* /last=selectthis /by varName.
*now we can delete the rest.
select if selectthis=1.
exe.
NOTE: make combineall wide enough to contain all the values of your most populated variable.

Splitting Values Between 2 Employees Possible Group By

We an incentive scheme that scored to staff via 'Points'. I have written an SP so that we can dynamically change these values day to day however I am struggling in my own head to figure the best way to split the values between two different agents.
The Setup
The source table simply looks like below:
Department | Policy |Opening Advisor | Closing Advisor | Agg Pts | Aff Pts | Rnl Pts |
Sales A | LYJX01PC01 | Sally | Sally | 0 | 3 | 0 |
Sales A | MUMP01TW01 | Sally | John | 0 | 0 | 3 |
This table is two separate tables, the first being the Opening Table and then the second being the Closing Table. These are joined by using the 'Branch' which is a column I've not put on here and then 'Policy' to keep it simple, Policy is what joins these 2 tables.
The Idea
The idea here is that the Points Per Policy are split 50/50 if the Opening Advisor and the Closing Advisor are different.
Line 1 the Opening and Closing Advisor is Sally, so for that policy she would receive all the points, however on Line 2 she opened the Policy however John closed it.
This would split the points out between them both i.e. 3/2 = 1.5. The output would then be similar to below:
The Output
Department | Policy | Advisor | Agg Pts | Aff Pts | Rnl Pts |
Sales A | LYJX01PC01 | Sally | 0 | 1.5 | 0 |
Sales A | LYJX01PC01 | John | 0 | 1.5 | 0 |
Sales A | MUMP01TW01 | Sally | 0 | 0 | 3 |
In my mind all I'm doing is GROUPING by Policy and Advisor and then splitting the points IF Opening / Closing Advisor differ, however putting that down in SQL I'm just turning circle and its one of those moments I need some exterior advice.

Matlab: find inner boundary of set of vertices

I have a set of (x,y) points defined in the following way:
map=[0,0;66,0;66,44;44,44;44,66;110,66;110,110;0,110];
There is then a function that connects these points (which are vertices, i.e. corner points) together to form a closed shape. The example vertices I have given form a shape something like this:
________________________________________
| |
| |
| |
| ____________________|
| |
| |_______
| |
| |
| |
| |
|___________________________|
I would like to now automatically generate a second set of vertices that form a boundary inside the shape, offset by some amount. I.e. this:
inner_boundary=[5,5;61,5;61,39;39,39;39,71;105,71;105,105;5,105];
________________________________________
| ___________________________________ |
| | | |
| | _____________________| |
| | | ____________________|
| | | |
| | | |_______
| | |________ |
| | | |
| | | |
| |______________________| |
|___________________________|
Any ideas on how to do this? I've been racking my brains but can't think of a robust way to do this. I need it to automatically do this for any input set of vertices. Also, to clarify - I am just interested in how to specify the set of vertices, not the drawing part.
Many thanks!
Here is a solution based on Image Processing Toolbox functions. The basic idea is as follows:
Use "poly2mask" to create a BW (0-1) image from the polygon
coordinates
Use "imerode" to erode the mask by 1 pixel
Use "bwboundaries" to trace the new, eroded, boundary
Code example:
x = [4 10 10 4 4];
y = [4 4 10 10 4];
mask = poly2mask(x,y,12,12);
mask_eroded = imerode(mask, 1);
newBnds = bwboundaries(mask_eroded);
newBnds = newBnds{1};
Note that the newBnds will probably contain more points than you want because it traces every single pixel on the boundary. You can write a simple iterative routine to discard non-endpoints.

How to find the nearest point in POSTGIS?

table A:
lat | long | the_geom | code | sign
13.8433095 | 100.6360357 | 0101000020E61.... | ABC | start_point
13.7544738 | 100.5459646 | 0101000020E6..... | ABC | end_point
13.4124215 | 100.6232332 | 0101000020E61.... | DEF | start_point
13.2423438 | 100.2324426 | 0101000020E6..... | DEF | end_point
table B:
lat | long | the_geom | code
13.7546285 | 100.5458729 | 0101000020E.... | ABC
13.7546698 | 100.5458513 | 0101000020E.... | ABC
13.7547107 | 100.5458233 | 0101000020E.... | DEF
...
I would like to find the nearest point of each point (start and end pojnt) compare with every points with the same code in table B ?
What's the best PostGIS function/PostgreSQL query to solve this ?
If you are using recent versions of the software, you can quickly find the K nearest neighbors to a point in PostGIS using KNN-GiST techniques. Small values of K are fastest, and 1 is about as small as they get, so this should work very well for you. I've only used KNN-GiST with text trigrams, but I know they work with PostGIS, too -- I just don't know the best page to read to get started with it. A web search for "postgis knn gist" shows lots of likely candidates.
After a long time question, i just found the solution of "Nearest Neighbor"
http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_nearest_neighbor_generic