Checking for equal bounds in PostGIS - postgis

I'm following the official PostGIS Introduction (https://www.postgis.net/workshops/postgis-intro/equality.html) and struggling on Chapter 22.1.3. The author want to compare the bounding boxes of different polygons with = to check if the extents are equal. Unfortunately running the code from the website doesn't give me expected result as in the training excercise.
Here's the code from the Introduction:
CREATE TABLE polygons (id integer, name varchar, poly geometry);
INSERT INTO polygons VALUES
(1, 'Polygon 1', 'POLYGON((-1 1.732,1 1.732,2 0,1 -1.732,
-1 -1.732,-2 0,-1 1.732))'),
(2, 'Polygon 2', 'POLYGON((-1 1.732,-2 0,-1 -1.732,1 -1.732,
2 0,1 1.732,-1 1.732))'),
(3, 'Polygon 3', 'POLYGON((1 -1.732,2 0,1 1.732,-1 1.732,
-2 0,-1 -1.732,1 -1.732))'),
(4, 'Polygon 4', 'POLYGON((-1 1.732,0 1.732, 1 1.732,1.5 0.866,
2 0,1.5 -0.866,1 -1.732,0 -1.732,-1 -1.732,-1.5 -0.866,
-2 0,-1.5 0.866,-1 1.732))'),
(5, 'Polygon 5', 'POLYGON((-2 -1.732,2 -1.732,2 1.732,
-2 1.732,-2 -1.732))');
SELECT a.name, b.name, CASE WHEN a.poly = b.poly
THEN 'Equal Bounds' ELSE 'Non-equal Bounds' end
FROM polygons as a, polygons as b LIMIT 10;
My Output:
"Polygon 1";"Polygon 1";"Equal Bounds"
"Polygon 1";"Polygon 2";"Non-equal Bounds"
"Polygon 1";"Polygon 3";"Non-equal Bounds"
"Polygon 1";"Polygon 4";"Non-equal Bounds"
"Polygon 1";"Polygon 5";"Non-equal Bounds"
"Polygon 2";"Polygon 1";"Non-equal Bounds"
"Polygon 2";"Polygon 2";"Equal Bounds"
"Polygon 2";"Polygon 3";"Non-equal Bounds"
"Polygon 2";"Polygon 4";"Non-equal Bounds"
"Polygon 2";"Polygon 5";"Non-equal Bounds"
Output from the tutorial:
What am I doing wrong? How can I compare the bounding boxes of a collection of polygons in a table?
I'm running PostgreSQL 9.4.26 with PostGIS 2.5.1 on Windows 10

The workshop is outdated.
The doc says
The = operator returns TRUE if the coordinates and coordinate order
geometry/geography A are the same as the coordinates and coordinate
order of geometry/geography B.
Changed: 2.4.0, in prior versions this was bounding box equality not a
geometric equality. If you need bounding box equality, use ~=
instead.

Related

Build array iterating over multiple indices in Julia

I want to obtain the following result with a more elegant syntax
julia> collect(Iterators.flatten([[(x,y) for y in 1:x] for x in 1:3]))
6-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 1)
(2, 2)
(3, 1)
(3, 2)
(3, 3)
I tried something like [(x,y) for y in 1:x, x in 1:3] but I get ERROR: UndefVarError: x not defined.
Just reverse the order of variables like this:
julia> [(x,y) for x in 1:3 for y in 1:x]
6-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 1)
(2, 2)
(3, 1)
(3, 2)
(3, 3)
I used to have also been struggled to remember the variable order. Until one day someone told me a secret: just treat the order of for loop in the list comprehension as usual except that the body is moved to the front.
For example, in normal order we write:
for x in 1:3
for y in 1:x
# do sth
end
end
Now we move the body part to the front and we have [ #= do sth =# for x in 1:3 for y in 1:x]

NumPy array loses dimension upon assignment/copy, why?

I have the following code:
print(type(a1), a1.shape)
a2 = a1 #.reshape(-1,1,2) this solves my problem
print(type(a2), a2.shape)
The output is:
<class 'numpy.ndarray'> (8, 1, 2)
<class 'numpy.ndarray'> (8, 2)
I know the (commented out) reshape solves my problem, however, I'd like to understand why a simple assignment results in losing the central dimension of the array.
Does anybody know what is going on? Why referring to the array with another name changes its dimensions?
Looking at the openCV script mentioned in the comments, the reshape to three dimensions is necessary because a dimension is being lost via Boolean indexing, and not by the assignment alone.
The names of the arrays in that script which motivated the question are p0 and good_new.
Here is a breakdown of the operations in that script:
p0 is a 3D array with shape (17, 1, 2).
The line:
p1, st, err = cv.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
creates new arrays, with array p1 having shape (17, 1, 2) and array st having shape (17, 1).
The assignment good_new = p1[st==1] creates a new array object by a Boolean indexing operation on p1. This is a 2D array has shape (17, 2). A dimension has been lost through the indexing operation.
The name p0 needs to be assigned back to the array data contained in good_new, but p0 also needs to be 3D. To achieve this, the script uses p0 = good_new.reshape(-1, 1, 2).
For completeness, it is worth summarising why the Boolean indexing operation in step (3) results in a dimension disappearing.
The Boolean array st == 1 has shape (17, 1) which matches the initial dimensions of p1, (17, 1, 2).
This means that the selection occurs in the second dimension of p1: the indexer array st == 1 is determining which arrays of shape (2,) should be in the resulting array. The final array will be of shape (n, 2), where n is the number of True values in the Boolean array.
This behaviour is detailed in the NumPy documentation here.
I am not sure why your are getting this.but it should not return like this.Can you please share how your a1 has been created.
I tried like below but not able to re create it
a1=np.ones((8,1,2),dtype=np.uint8)
print(type(a1), a1.shape)
<class 'numpy.ndarray'> (8, 1, 2)
a2=a1
print(type(a2), a2.shape)
<class 'numpy.ndarray'> (8, 1, 2)`

Grouping lines considering intersections of each line using python

There are 5 lines. I want to group them considering whether they intersect or not by limiting to the two end points of each line.
I want to get the logic for any of the lines, not being limited to the given scenario.
Array of 5 lines (coordinates of end points).
lines_all = [[(1, 10), (5, 10)],[(3, 5), (5, 5)],[(3, 10), (3, 13)],[(5,10),(5,13)],[(3,13),(4,13)]]
Then finally I want to get the following array list.
result = [[[(1, 10), (5, 10)], [(3, 10), (3, 13)],[(3, 13), (4, 13)]], [[(1, 10), (5, 10)], [(5, 10), (5, 13)]],[(3, 5), (5, 5)]]
To find all line segment intersections, you can use Bentley-Ottmann algorithm.
Arbitrary found Python implementation

Finding the set of all winning tic tac toe board states

Here's my problem. I want to create an algorithm which generates an array of arrays of every possible winning board state for an n-dimensional tic-tac-toe board. Say you have an n = 2 board, meaning 2x2, then the function should return the following array:
wins = [
[1,2],
[1,3],
[1,4],
[2,4]
]
I know this isn't specifically a MATLAB problem, however I'm trying to expand my understanding of how MATLAB works. My general idea is an algorithm that does the following:
generate an n-dimensional board of zeros
1. Go to the first cell, record that index ([1,])
2. Go to the end of the row, and that's your first board state ([1,2])
3. Go to the end of the column, that's your second board state ([1,3])
4. Go to the end of the diagonal, that's your third board state ([2,3])
5. Advance to the next cell, repeat, checking if you have already created that board state first ([2,4] should be the only one it hasn't done)
I think I'm overthinking the problem, but I'm not sure how to approach it. Can someone give me some guidance how to do this in a MATLAB-y way? My guess is that traversing the matrix and just picking whole rows/colums/diagonals is easy, it's the 'checking if it exists' part that I'm not getting. How would you call this algorithm, in general? Thanks for any help!
Better idea: you don't do this square by square, you do this by dimension. For each dimension on the board, you have these possibilities for the coordinate to vary or not through winning combinations:
iterate through all the possible values, low to high
iterate through all the possible values, high to low
hold constant as the other dimensions iterate, but do so for each value in range, repeating for the other coordinates.
For instance, for a 4^3 board, let's look at the last coordinate (call them x1, x2, x3), x3. Assume that you've already determined x1 will iterate low to high, x2 is constant at 2. You will now treat x3 with:
iterate through all the possible values, low to high
(1, 2, 1), (2, 2, 2), (3, 2, 3)
iterate through all the possible values, high to low
(1, 2, 3), (2, 2, 2), (3, 2, 1)
hold constant as the other dimensions iterate, but do so for each value in range, repeating for the other coordinates.
(1, 2, 1), (2, 2, 1), (3, 2, 1)
(1, 2, 2), (2, 2, 2), (3, 2, 2)
(1, 2, 3), (2, 2, 3), (3, 2, 3)
Does that get you moving?

Binning then sorting arrays in each bin but keeping their indices together

I have two arrays and the indices of these arrays are related. So x[0] is related to y[0], so they need to stay organized. I have binned the x array into two bins as shown in the code below.
x = [1,4,7,0,5]
y = [.1,.7,.6,.8,.3]
binx = [0,4,9]
index = np.digitize(x,binx)
Giving me the following:
In [1]: index
Out[1]: array([1, 2, 2, 1, 2])
So far so good. (I think)
The y array is a parameter telling me how well measured the x data point is, so .9 is better than .2, so I'm using the next code to sort out the best of the y array:
y.sort()
ysorted = y[int(len(y) * .5):]
which gives me:
In [2]: ysorted
Out[2]: [0.6, 0.7, 0.8]
giving me the last 50% of the array. Again, this is what I want.
My question is how do I combine these two operations? From each bin, I need to get the best 50% and put these new values into a new x and new y array. Again, keeping the indices of each array organized. Or is there an easier way to do this? I hope this makes sense.
Many numpy functions have arg... variants that don't operate "by value" but rather "by index". In your case argsort does what you want:
order = np.argsort(y)
# order is an array of indices such that
# y[order] is sorted
top50 = order[len(order) // 2 :]
top50x = x[top50]
# now top50x are the x corresponding 1-to-1 to the 50% best y
You should make a list of pairs from your x and y lists
It can be achieved with the zip function:
x = [1,4,7,0,5]
y = [.1,.7,.6,.8,.3]
values = zip(x, y)
values
[(1, 0.1), (4, 0.7), (7, 0.6), (0, 0.8), (5, 0.3)]
To sort such a list of pairs by a specific element of each pair you may use the sort's key parameter:
values.sort(key=lambda pair: pair[1])
[(1, 0.1), (5, 0.3), (7, 0.6), (4, 0.7), (0, 0.8)]
Then you may do whatever you want with this sorted list of pairs.

Resources