postgis convert Points to polygon - postgresql

what is the easy way to convert points to polygon?
i've tried this query
SELECT ST_GeomFromText('POLYGON((157 -536.0,157 -537.0,157 -538.0,157 -539.0,157 -540.0,157 -541.0,157 -542.0,157 -543.0,157 -544.0,157 -545.0,158 -545.0,159 -545.0,160 -545.0,161 -545.0,162 -545.0,163 -545.0,164 -545.0,165 -545.0,165 -544.0,165 -543.0,165 -542.0,165 -541.0,165 -540.0,165 -539.0,165 -538.0,165 -537.0,165 -536.0,164 -536.0,163 -536.0,162 -536.0,161 -536.0,160 -536.0,159 -536.0,158 -536.0,157.0 -536.0))');
but its results are not as expected as shown below
which is supposed to be like this

Obviously your points are not in the correct order to define a polygon., and as the commenter pointed out, you have more than one polygons.
You could divide them into sets that make each polygon (manually?), and construct a multipolygon as follows:
SELECT ST_AsText(ST_Collect(ARRAY[ST_GeomFromText('POLYGON(..first polygon...)'),ST_GeomFromText('POLYGON(..2nd polygon...)',...,ST_GeomFromText('POLYGON(..last polygon...)')]));

Related

PostGIS: Two equal geometries are not equal?

I have two geometries in different tables which look like the same, but one is valid and the other is invalid. I checked it out:
select ST_IsValid(_s.geom) as _gvalid,
ST_IsValid(s.geom) as gvalid,
_s.geom = s.geom as geom_bin_equal,
ST_SRID(_s.geom)=ST_SRID(s.geom) as srid_equal,
ST_EQUALS(_s.geom, s.geom),
ST_AsText(_s.geom) = ST_AsText(s.geom) as text_equal
from _spatial_object _s, spatial_object s
where _s.id_spatial_object = 314 and s.id_spatial_object = 314
Output here:
How on the earth it could be?
Actually, the both geometries should be invalid (Interior is disconnected at or near point 58.182000000000002 51.457000000000001)
Geometry:
POLYGON((58.169 51.456,58.176 51.458,58.18 51.458,58.182 51.457,58.183 51.456,58.182 51.453,58.184 51.451,58.182 51.449,58.183 51.448,58.181 51.445,58.179 51.443,58.177 51.444,58.179 51.445,58.178 51.446,58.178 51.448,58.178 51.448,58.177 51.448,58.173 51.447,58.17 51.449,58.173 51.45,58.174 51.451,58.178 51.451,58.178 51.452,58.178 51.452,58.176 51.452,58.173 51.451,58.169 51.456),(58.169 51.456,58.1732222222222 51.4569444444444,58.182 51.457,58.169 51.456))
select ST_ISValid(geom), ST_IsValid(ST_GeomFromText(ST_AsText(geom))) from _spatial_object
outputs
true false
Prior to version 2.4, the equality using = was relying on a bounding box comparison only, so two very different geometries could still be considered as being equal.
When using ST_Equals, the two geometries must "look" the same (but the vertices order does not matter). However, the doc notes that
[Important]
This function will return false if either geometry is invalid except
in the case where they are binary equal.
but also mentions that
Changed: 2.2.0 Returns true even for invalid geometries if they are
binary equal
So because you are using an older version, the result is unreliable / false.

Different ST_Distance calculation with degrees and metres in PostGIS

I have noticed that sometimes the results from ST_Distance for geometry types do not correspond correctly to those for geography types.
For example:
SELECT ST_Distance('SRID=4326;MULTIPOLYGON(((13.1654379639367 48.0163296656575,
13.1654405823308 48.0163326202901,13.1654809135407 48.0163781648167,
13.1655095556032 48.0164104945946,13.1656825124596 48.0166031792699,
13.1658285825017 48.0167559797112,13.1658385904811 48.0167667179682,
13.1660097634653 48.0169315381006,13.1661737540995 48.0170911295992,
13.166336100685 48.0172329598378,13.1677079127931 48.0150783894135,
13.1677278111466 48.0150450062427,13.1670716137939 48.0148839705059,
13.1667911667995 48.0148062288149,13.1665512255895 48.0147411405409,
13.1665145733757 48.0147311909654,13.1654379639367 48.0163296656575)))'::geometry,
'SRID=4326;POINT(16.096346 47.2786129)'::geometry);
returns 3.0197908442784636 as a result in degrees.
But, when computing the distance of the same shapes in metres:
SELECT ST_Distance(gg1,gg2) from (select 'SRID=4326;MULTIPOLYGON(((13.1654379639367 48.0163296656575,
13.1654405823308 48.0163326202901,13.1654809135407 48.0163781648167,13.1655095556032 48.0164104945946,
13.1656825124596 48.0166031792699,13.1658285825017 48.0167559797112,13.1658385904811 48.0167667179682,
13.1660097634653 48.0169315381006,13.1661737540995 48.0170911295992,13.166336100685 48.0172329598378,
13.1677079127931 48.0150783894135,13.1677278111466 48.0150450062427,13.1670716137939 48.0148839705059,
13.1667911667995 48.0148062288149,13.1665512255895 48.0147411405409,13.1665145733757 48.0147311909654,
13.1654379639367 48.0163296656575)))'::geography as gg1,
'SRID=4326;POINT(16.096346 47.2786129)'::geography as gg2) as foo;
it returns 0 metres. This can't be right. By looking the shapes in wkt playground the distance is indeed much more than 0 metres.
Any idea of what I could be doing wrong?
Thank you!

Get point along a linestring that is two feet away from the first point

I have the following linestring:
SELECT ST_GeomFromText('LINESTRING(-97.83396022 29.98609860,-97.83391790 29.98613790)',4326);
I need to add a point between the linestring, which is 2 feet from the first point
You can use ST_LineInterpolatePoint.
Since it takes a proportion of the line, the first step is to compute it: convert 2ft to meters, divide by the length of the line in meters, that you get by casting it to geography.
WITH src(geom) AS (values (ST_GeomFromText('LINESTRING(-97.83396022 29.98609860,-97.83391790 29.98613790)',4326)))
SELECT ST_AsText(ST_LineInterpolatePoint(geom, 2 * 0.3048/ st_length(geom::geography)))
FROM src;
st_astext
-------------------------------------------
POINT(-97.8339558996568 29.9861026120389)
To create a line from the start that is 2ft long, you can use st_lineSubstring instead
SELECT st_lineSubstring(geom, 0, 2 * 0.3048/ st_length(geom::geography))

Performing Kernel Density Estimations in MATLAB

I have been using MATLAB to perform Kernel Density Estimations (KDE) on UTM data (X and Y coordinates). I ran into a problem that I do not seem to be understanding.
I perform the KDEs with a sample of 45 points. Everything works fine and I produce the graphs with contours.
[bandwidth,density,X,Y]=kde2d(data)
The function kde2d is code by Zdravko Botev. I obtained it from his file exchange on MathWorks. The variable 'data' is a 45x2 array of my data. The first column holds the X coordinates and the second the Y.
The problem comes when I try to do the same line of code on a subset of those 45 points. I get a recurring error:
Error using fzero (line 274)
The function values at the interval endpoints must differ in sign.
Error in kde2d (line 101)
t_star=fzero(#(t)(t-evolve(t)),[0,0.1]);
I get the same error for a bunch of those subsets on a bunch of different sets of 45 points.
The complete set has these 45 values:
1594436.281 572258.1272
1594418.48 572357.5859
1594471.362 572385.5186
1594516.726 572266.8206
1594415.313 572369.2754
1594519.701 572272.7153
1594415.377 572363.4139
1594468.365 572381.5779
1594518.139 572276.6059
1594425.496 572271.6874
1594524.259 572272.7651
1594502.555 572172.8749
1594516.747 572264.867
1594485.314 572360.2689
1594476.027 572375.7997
1594556.087 572419.6609
1594522.718 572274.7021
1594472.775 572395.3039
1594554.568 572419.6443
1594527.255 572276.7054
1594474.315 572393.3669
1594522.697 572276.6557
1594471.319 572389.4262
1594460.854 572373.6799
1594546.022 572228.0609
1594460.79 572379.5414
1594468.323 572385.4855
1594466.953 572371.7926
1594519.722 572270.7614
1594396.76 572398.3826
1594468.131 572403.0693
1594418.288 572375.1697
1594396.377 572433.5499
1594448.287 572271.9361
1594510.541 572276.523
1594424.466 572226.7345
1594413.773 572371.2124
1594511.848 572296.0774
1594513.367 572296.094
1594424.488 572224.7805
1594468.152 572401.1153
1594421.37 572371.2953
1594446.768 572271.9195
1594468.152 572401.1153
1594448.799 572225.0457
One of the subsets I am trying to use is this:
1594436.281 572258.1272
1594418.48 572357.5859
1594471.362 572385.5186
1594516.726 572266.8206
1594415.313 572369.2754
1594519.701 572272.7153
1594415.377 572363.4139
1594468.365 572381.5779
1594518.139 572276.6059
1594425.496 572271.6874
I am not sure if I should include any of Botev's code. I am hoping that the error message can be explained on its own. If not I can provide more. Thank you very much.

Function equivalent to SUM() for multiplication in SQL Reporting

I'm looking for a function or solution to the following:
For the chart in SQL Reporting i need to multiply values from a Column A. For summation i would use =SUM(COLUMN_A) for the chart. But what can i use for multiplication - i was not able to find a solution so far?
Currently i am calculating the value of the stacked column as following:
=ROUND(SUM(Fields!Value_Is.Value)/SUM(Fields!StartValue.Value),3)
Instead of SUM i need something to multiply the values.
Something like that:
=ROUND(MULTIPLY(Fields!Value_Is.Value)/MULTIPLY(Fields!StartValue.Value),3)
EDIT #1
Okay tried to get this thing running.
The expression for the chart looks like this:
=Exp(Sum(Log(IIf(Fields!Menge_Ist.Value = 0, 10^-306, Fields!Menge_Ist.Value)))) / Exp(Sum(Log(IIf(Fields!Startmenge.Value = 0, 10^-306, Fields!Startmenge.Value))))
If i calculate my 'needs' manually i have to get the following result:
In my SQL Report i get the following result:
To make it easier, these are the raw values:
and you have the possibility to group the chart by CW, CQ or CY
(The values from the first pictures are aggregated Sum values from the raw values by FertStufe)
EDIT #2
Tried your expression, which results in this:
Just to make it clear:
The values in the column
=Value_IS / Start_Value
in the first picture are multiplied against each other
0,9947 x 1,0000 x 0,59401 = 0,58573
Diffusion Calenderweek 44 Sums
Startvalue: 1900,00 Value Is: 1890,00 == yield:0,99474
Waffer unbestrahlt Calenderweek 44 Sums
Startvalue: 620,00 Value Is: 620,00 == yield 1,0000
Pellet Calenderweek 44 Sums
Startvalue: 271,00 Value Is: 160,00 == yield 0,59041
yield Diffusion x yield Wafer x yield Pellet = needed Value in chart = 0,58730
EDIT #3
The raw values look like this:
The chart ist grouped - like in the image - on these fields
CY (Calendar year), CM (Calendar month), CW (Calendar week)
You can download the data as xls here:
https://www.dropbox.com/s/g0yrzo3330adgem/2013-01-17_data.xls
The expression i use (copy / past from the edit window)
=Exp(Sum(Log(Fields!Menge_Ist.Value / Fields!Startmenge.Value)))
I've exported the whole report result to excel, you can get it here:
https://www.dropbox.com/s/uogdh9ac2onuqh6/2013-01-17_report.xls
it's actually a workaround. But I am pretty sure is the only solution for this infamous problem :D
This is how I did:
Exp(∑(Log(X))), so what you should do is:
Exp(Sum(Log(Fields!YourField.Value)))
Who said math was worth nothing? =D
EDIT:
Corrected the formula.
By the way, it's tested.
Addressing Ian's concern:
Exp(Sum(Log(IIf(Fields!YourField.Value = 0, 10^-306, Fields!YourField.Value))))
The idea is change 0 with a very small number. Just an idea.
EDIT:
Based on your updated question this is what you should do:
Exp(Sum(Log(Fields!Value_IS.Value / Fields!Start_Value.Value)))
I just tested the above code and got the result you hoped for.