Polygon Intersection with LineString (closed curve) - geopandas

I have a polygon as such
polygon_coords = [(-13585557.004033158, 4498795.070440721), (-13585215.14187693, 4500515.198409752), (-13581108.78850055, 4497863.34704348), (-13581192.612077117, 4497554.426176021), (-13580596.94148188, 4497528.496299017), (-13580385.211810393, 4497383.150012096), (-13579492.874772193, 4497412.443364113), (-13579516.36318475, 4497381.46809963), (-13579512.689641556, 4496699.194502575), (-13579497.884149278, 4495658.910722646), (-13579543.747779485, 4495404.005766705), (-13579528.051731283, 4493390.628219194), (-13581939.67717983, 4494259.602208199), (-13585136.884274904, 4495136.215086736), (-13585127.088159712, 4495209.923404868), (-13585108.943082713, 4497557.089248097), (-13585088.237657426, 4497826.48350398), (-13584837.546164159, 4498714.608439874), (-13585109.833638642, 4498744.185863254), (-13585477.18795826, 4498785.958859128), (-13585557.004033158, 4498795.070440721)]
polygon = Polygon(polygon_coords)
line_coords = [(-13581392.216297297, 4494641.272566045), (-13581395.793280436, 4494647.557676422)]
list(polygon.intersection(LineString(line_coords)).coords)
>>> [(-13581392.216297297, 4494641.272566045), (-13581395.793280436, 4494647.557676422)]
list(polygon.intersection(LineString(line_coords + [line_coords[0]])).coords)
>>> [(-13581392.216297297, 4494641.272566045), (-13581395.793280436, 4494647.557676422)]
Intersection of LineString(line_coords) and LineString(line_coords + [line_coords[0]]) gives the same result. I was expecting the intersection to have all the coordinates.. Am I missing something ?

intersection is a complex spatial operation, and shapely does not return the same object as is provided in the arguments, even if the intersecting objects are identical.
Seen here - even if we're just getting the intersection of the line with itself, shapely has returned a new object, though the coordinates are equal:
In [13]: line = LineString(line_coords)
In [14]: hex(id(line))
Out[14]: '0x1041f1a50'
In [15]: hex(id(line.intersection(line)))
Out[15]: '0x10569b9d0'
In [16]: line == line.intersection(line)
Out[16]: True
Since the line (A, B, A) is equivalent in shape to (A, B), shapely will never return (A, B, A) from the intersection. There's also no reason why it wouldn't return (B, A) for polygon.intersection(line), as the intersection has no concept of directionality.

Related

Identifying non-intersecting (super-)sets

I am looking for an algorithm to identify non-intersecting (super-)sets in a set of sets.
Lets, assume I have a set of sets containing the sets A, B, C and D, i.e. {A, B, C, D}. Each set may or may not intersect some or all of the other sets.
I would like to identify non-intersecting (super-)sets.
Examples:
If A & B intersect and C & D intersect but (A union B) does not intersect (C union D), I would like the output of {(A union B), (C union D)}
If only C & D intersect, I would like the output {A, B, (C union D)}
I am sure this problem has long been solved. Can somebody point me in the right direction?
Even better would be of course if somebody had already done the work and had an implementation in python they were willing to share. :-)
I would turn this from a set problem into a graph problem by constructing a graph whose nodes are the graphs with edges connecting sets with an intersection.
Here is some code that does it. It takes a dictionary mapping the name of the set to the set. It returns an array of sets of set names that connect.
def set_supersets (sets_by_label):
element_mappings = {}
for label, this_set in sets_by_label.items():
for elt in this_set:
if elt not in element_mappings:
element_mappings[elt] = set()
element_mappings[elt].add(label)
graph_conn = {}
for elt, sets in element_mappings.items():
for s in sets:
if s not in graph_conn:
graph_conn[s] = set()
for t in sets:
if t != s:
graph_conn[s].add(t)
seen = set()
answer = []
for s, sets in graph_conn.items():
if s not in seen:
todo = [s]
this_group = set()
while 0 < len(todo):
t = todo.pop()
if t not in seen:
this_group.add(t)
seen.add(t)
for u in graph_conn[t]:
todo.append(u)
answer.append(this_group)
return answer
print(set_supersets({
"A": set([1, 2]),
"B": set([1, 3]),
"C": set([4, 5]),
"D": set([3, 6])
}))

Given a set of lattice points, how many group of points are there?

The idea is that given a set of lattices points in the plane, determine how many "group" of points there are in the given set.
A group of points is defined as follow:
Given a set S of lattice points,
it is said that these points form a group of points if and only if:
for each a of S the distance of the nearest point(s) is 1
The function must return a list with all the groups of points existing.
input: --> point: list
output: --> group: list
If it's possible to get a better algorithm beacause I'm not sure if this code work for every set of points.
My code look like this
def walk_point_path(points):
groups = []
points_x = sorted(points, key=lambda x: x[1])
visited = [points_x[0]]
q = [points_x[0]]
while points_x:
while q:
x, y = q.pop()
for x, y in (x, y - 1), (x, y + 1), (x - 1, y), (x + 1, y):
if [x, y] not in visited and [x, y] in points_x:
q.append([x, y])
visited.append([x, y])
groups.append(visited)
for point in visited:
points_x.remove(point)
if len(points_x) > 0:
q = [points_x[0]]
visited = [points_x[0]]
return groups
Consider some good implementation of connected-components labeling algorithm.
Your current approach exploits flood-fill algorithm (One component at a time kind) to get points in group.

sympy nsolve typeError with Matrix starting vector

I'm getting a TypeError with nsolve when I give it a Matrix for the starting vector. Notably, nsolve is perfectly fine with the fact that the equation is a Matrix expression. Here's a basic example:
import sympy as sy
v = sy.Matrix(sy.symarray("v", (2,)))
w = sy.Matrix([17, 23])
equation = v - w
The following line gives a TypeError: cannot create mpf from Matrix([[17],[23]]):
sy.nsolve(equation, v, w)
The following line is a kludgy workaround which gives the correct output, Matrix([[17.0],[23.0]]):
sy.nsolve(equation, v, w.T.tolist()[0])
Is there a better solution than this workaround?
The workaround you have is necessary, given the following:
nsolve passes the x0 argument directly to mpmath.findroot, on this line
findroot only supports iterables in x0 that satisfy isinstance(x0, (list, tuple)), on this line. Moreover it has to be a flat tuple or list; its elements are assumed to be scalars in the subsequent x0 = [ctx.convert(x) for x in x0].
A SymPy matrix is not an instance of either list or tuple. Also, w.tolist() is not enough because the resulting list is nested. Hence the need for w.T.tolist()[0].
This is now an open issue in SymPy repo.

Image Neighbourhood Processing in Haskell

I'm new to Haskell, and trying to learn it by thinking in terms of image processing.
So far, I have been stuck thinking about how you would implement a neighbourhood-filtering algorithm in Haskell (or any functional programming language, really).
How would a spatial averaging filter (say 3x3 kernel, 5x5 image) be written functionally? Coming from an entirely imperative background, I can't seem to come up with a way to either structure the data so the solution is elegant, or not do it by iterating through the image matrix, which doesn't seem very declarative.
Working with neighborhoods is easy to do elegantly in a functional language. Operations like convolution with a kernel are higher order functions that can be written in terms of one of the usual tools of functional programming languages - lists.
To write some real, useful code, we'll first play pretend to explain a library.
Pretend
You can think of each image as a function from a coordinate in the image to the value of the data held at that coordinate. This would be defined over all possible coordinates, so it would be useful to pair it with some bounds which tell us where the function is defined. This would suggest a data type like
data Image coordinate value = Image {
lowerBound :: coordinate,
upperBound :: coordinate,
value :: coordinate -> value
}
Haskell has a very similar data type called Array in Data.Array. This data type comes with an additional feature that the value function in Image wouldn't have - it remembers the value for each coordinate so that it never needs to be recomputed. We'll work with Arrays using three functions, which I'll describe in terms of how they'd be defined for Image above. This will help us see that even though we are using the very useful Array type, everything could be written in terms of functions and algebraic data types.
type Array i e = Image i e
bounds gets the bounds of the Array
bounds :: Array i e -> (i, i)
bounds img = (lowerBound img, upperBound img)
The ! looks up a value in the Array
(!) :: Array i e -> i -> e
img ! coordinate = value img coordinate
Finally, makeArray builds an Array
makeArray :: Ix i => (i, i) -> (i -> e) -> Array i e
makeArray (lower, upper) f = Image lower upper f
Ix is a typeclass for things that behave like image coordinates, they have a range. There are instances for most of the base types like Int, Integer, Bool, Char, etc. For example the range of (1, 5) is [1, 2, 3, 4, 5]. There's also an instances for products or tuples of things that themselves have Ix instances; the instance for tuples ranges over all combinations of the ranges of each component. For example, range (('a',1),('c',2)) is
[('a',1),('a',2),
('b',1),('b',2),
('c',1),('c',2)]`
We are only interested in two functions from the Ix typeclass, range :: Ix a => (a, a) -> [a] and inRange :: Ix a => a -> (a, a) -> Bool. inRange quickly checks if a value would be in the result of range.
Reality
In reality, makeArray isn't provided by Data.Array, but we can define it in terms of listArray which constructs an Array from a list of items in the same order as the range of its bounds
import Data.Array
makeArray :: (Ix i) => (i, i) -> (i -> e) -> Array i e
makeArray bounds f = listArray bounds . map f . range $ bounds
When we convolve an array with a kernel, we will compute the neighborhood by adding the coordinates from the kernel to the coordinate we are calculating. The Ix typeclass doesn't require that we can combine two indexes together. There's one candidate typeclass for "things that combine" in base, Monoid, but there aren't instances for Int or Integer or other numbers because there's more than one sensible way to combine them: + and *. To address this, we'll make our own typeclass Offset for things that combine with a new operator called .+.. Usually we don't make typeclasses except for things that have laws. We'll just say that Offset should "work sensibly" with Ix.
class Offset a where
(.+.) :: a -> a -> a
Integers, the default type Haskell uses when you write an integer literal like 9, can be used as offsets.
instance Offset Integer where
(.+.) = (+)
Additionally, pairs or tuples of things that Offset can be combined pairwise.
instance (Offset a, Offset b) => Offset (a, b) where
(x1, y1) .+. (x2, y2) = (x1 .+. x2, y1 .+. y2)
We have one more wrinkle before we write convolve - how will we deal with the edges of the image? I intend to pad them with 0 for simplicity. pad background makes a version of ! that's defined everywhere, outside the bounds of an Array it returns the background.
pad :: Ix i => e -> Array i e -> i -> e
pad background array i =
if inRange (bounds array) i
then array ! i
else background
We're now prepared to write a higher order function for convolve. convolve a b convolves the image b with the kernel a. convolve is higher order because each of its arguments and its result is an Array, which is really a combination of a function ! and its bounds.
convolve :: (Num n, Ix i, Offset i) => Array i n -> Array i n -> Array i n
convolve a b = makeArray (bounds b) f
where
f i = sum . map (g i) . range . bounds $ a
g i o = a ! o * pad 0 b (i .+. o)
To convolve an image b with a kernel a, we make a new image defined over the same bounds as b. Each point in the image can be computed by the function f, which sums the product (*) of the value in the kernel a and the value in the padded image b for each offset o in the range of the bounds of the kernel a.
Example
With the six declarations from the previous section, we can write the example you requested, a spatial averaging filter with a 3x3 kernel applied to a 5x5 image. The kernel a defined below is a 3x3 image that uses one ninth of the value from each of the 9 sampled neighbors. The 5x5 image b is a gradient increasing from 2 in the top left corner to 10 in the bottom right corner.
main = do
let
a = makeArray ((-1, -1), (1, 1)) (const (1.0/9))
b = makeArray ((1,1),(5,5)) (\(x,y) -> fromInteger (x + y))
c = convolve a b
print b
print c
The printed input b is
array ((1,1),(5,5))
[((1,1),2.0),((1,2),3.0),((1,3),4.0),((1,4),5.0),((1,5),6.0)
,((2,1),3.0),((2,2),4.0),((2,3),5.0),((2,4),6.0),((2,5),7.0)
,((3,1),4.0),((3,2),5.0),((3,3),6.0),((3,4),7.0),((3,5),8.0)
,((4,1),5.0),((4,2),6.0),((4,3),7.0),((4,4),8.0),((4,5),9.0)
,((5,1),6.0),((5,2),7.0),((5,3),8.0),((5,4),9.0),((5,5),10.0)]
The convolved output c is
array ((1,1),(5,5))
[((1,1),1.3333333333333333),((1,2),2.333333333333333),((1,3),2.9999999999999996),((1,4),3.6666666666666665),((1,5),2.6666666666666665)
,((2,1),2.333333333333333),((2,2),3.9999999999999996),((2,3),5.0),((2,4),6.0),((2,5),4.333333333333333)
,((3,1),2.9999999999999996),((3,2),5.0),((3,3),6.0),((3,4),7.0),((3,5),5.0)
,((4,1),3.6666666666666665),((4,2),6.0),((4,3),7.0),((4,4),8.0),((4,5),5.666666666666666)
,((5,1),2.6666666666666665),((5,2),4.333333333333333),((5,3),5.0),((5,4),5.666666666666666),((5,5),4.0)]
Depending on the complexity of what you want to do, you might consider using more established libraries, like the oft recommended repa, rather than implementing an image processing kit for yourself.

Finding the point which minimizes the distance given a point in space and constraints?

I have a question regarding an algorithm:
We have a fixed point in 2D space let's call it S(x,y) and the length of two links joining (L1 and L2). These two links are connected at a common joint called E(x,y). And we have another point in the space which is end point of the L2 which we call F(x,y).
So we L1 have two end points S and E where as L2 has E and F.
When we are given a point P(x,y) in space. How can we find the coordinate of F(x,y) which is closest to P? I wanted to find the angle of θ1 and θ2 which takes the links L1 and L2 to that point?
See this link to get the graphical representation of my problem
See this pic http://postimage.org/image/qlekcv1qz/, where you will be able to see the real problem I have right now.
So I have formulated this as optimization problem. Where the Objective function is:
* arg min |P-F|
with constraints θ1 and θ2 where θ1 ∈ [ O , π] and θ2 ∈ [ O , π/2].
So we have,
* xE = xS + L1 * Cosθ1 and yE = yS + L1 * Sinθ1
* xF = xE + L2 * Cos (θ1 + θ2 ) and yF = yE + L2 * sin ( θ1 + θ2)
Here we have length of L1 = 105 and L2 = 113.7 and Point S is the origin i.e xS = O and yS = O.
Can you give a hint how code up my function or any optimization problem which gives me the values of θ1 and θ2, such that the distance between Point F and point P is minimized.
So if I understand correctly, your description is equivalent of having two rigid rods of length L1 and L2, with one end of L1 fixed at S, the other end connected to L2 by a flexible joint (at some undefined point E), and you want to get the other end of L2 (point F) as close to some point P as possible. If this is the case then:
If |L1-L2| < |P-S| < |L1+L2| then F = P
If |L1-L2| > |P-S| then F = S + (P-S)*|L1-L2|/|P-S|
If |P-S| > |L1+L2| then F = S + (P-S)*|L1+L2|/|P-S|
Is that what you want?
See imnage
http://postimage.org/image/l1ktt0qtb/
If point P is closer to point S than the distance |L1-L2| (assuming they are unequal), then point F cannot 'reach' point P, even with the angle at E bent to 180 ndegrees. Then the closest you can get is somewhere on the the circle with radius |L1-L2| and centre S. In this case the best F is given by the vector with direction (P-S), and magnitude |L1-L2|, my case 2 above and Figure A below. Note that if L1=L2 this will never be the case.
If point P is further from point S than the distance |L1+L2|, then point F cannot 'reach' point P, even with the angle at E straightened to 0 degrees. Then the closest you can get is aomewhere on the the circle with radius |L1+L2| and centre S. In this case the best F is given by the vector with direction (P-S), and magnitude |L1+L2|, my case 3 above and Figure B below.
If point P is betwen the two limiting circles, then there will be two solutions (one as shown in Figure 3 below, and the other with L1 and L2 reflected in the mirror line formewd by the vector P-S. In this case the 'best' F is equal to point P.
If you want to know the angles Theta1 and Theta 2 then that is a different question (I see you have added that now).
Use the cosine rule for triangles with no right angle.
The rule is
C = acos[(a^2 + b^2 - c^2)/(2ab)]
where a triangle has sides of length a,b, and c, and C is the angle between sides a and b. You are trying to produce a triangle with sides l1, l2, and d=|S-P|, which will be possible so as long as no two of the lengths are shorter (in sum) than the third one.
By substituting l1, l2, and d for a,b, anc c appropriately you will be able to solve for each of the internal angles, A, B, and C. Then you can use these angles A,B,C plus the angle between the vector P-S and horizontal (call that D perhaps?) to calculate your theta1 and theta2.

Resources