Distance outside shapely.Polygon - python

How do I establish the distance a point is from a polygon? If the point is within the polygon the result should be 0.
I'm guessing something like:
def distance_from(poly,point):
if poly.contains(point): return 0
return poly.exterior.distance(point)

I'd like to clarify things up a bit:
The instances which are passed to the distance_from function are made of the classes shapely.geometry.polygon.Polygon and shapely.geometry.point.Point from the shapely.geometry module of the Shapely Python package for computational geometry. (For more info on shapely and geometric objects have a look in the manual : Shapely Python Package, Geometric Objects).
The distance method of a geometric object returns the minimum float distance to another geometric object as described here in the manual. The exterior of a polygon is an instance of shapely.geometry.polygon.LinearRing which makes up the boundary of a polygon (although it is not to be mixed up with the boundary attribute of a polygon which returns a LineString). So for the case above you don't need to to explicitly use poly.exterior.distance(point) because the minimum distance is the same for the whole polygon as it is for its boundary. They have exactly the same shape only a different geometry type.
It would be less error prone if you would just use poly.distance(point) because that way if the point of interest lies within the interior (more info here) of the polygon it is directly clear that it contains it, so you do not need an explicit check and also the distance from a point within the interior to itself is then 0. It would be different if you would try to get the distance from the exterior (which, as explained above, is a LinearRing, i.e. a closed LineString) to a point which lies in the "inner" part. In this case you would get the minimum distance between the point in the "inner" part and the surrounding linear ring.
For further info about binary relationships (i.e between a geometric object and another, which covers contains, within, touches etc.) refer to this part of the manual and for those interested in the underlying DE-9IM relationships (which are a way to clearly identify the way a geometric objects relates to another) refer to this part.
Shapely is a python wrapper for the GEOS suite which itself is a C++ port of JTS. On the JTS page under the link Feature sheet more information can be found about how spatial relationships are checked and computed

Related

Fastest polygon union when all polygons are rectangles?

At my job we have to union many polygons together for some spatial aggregation. One problem we have is limited runtime and memory constraints (aws lambda), so for larger feature collections our current geopandas implementations hit their limits.
My main question is: is there a faster polygon union / algorithm I could be using other than shapely unary union (which i assume is what geopandas dissolve is using), that could take advantage of the fact that all polygons are rectangles, with no holes. (I.e. hoping that unary union having to account for arbitrary shapes may leave performance on the table)
The following algorithm doesn't really use the rectangular property of items.
The initial process is to create additional points for each intersection : in case of intersection between two rectangle sides, side(s) may be split in 2 or more polygon segment.
The next step consist in finding the top left point of all polygons and
assume that the virtual previous point is at the left of this point.
To find the next point of the envelope, choose among all polygons sharing the current point, the vector CN (current point to next point) whose angle CP^CN is the maximum.
When next point is top left point, it is completed.
Process all points and remove those that are inside the envelope(s).
If there are remaining points, use the same algorithm to find other envelopes (archipelago case).
For performance issues, I recommend to have a relation between points and the list of [polygon, point index] to which points belong.

How to determine whether a point is inside or outside a 3D model computationally

I have a .obj and .ply file of a 3D model.
What I want to do is read this 3D model file and see if a list of 3D coordinates are either inside or outside the 3D model space.
For example, if the 3D model is a sphere with radius 1, (0,0,0) would be inside (True) and (2,0,0) would be outside (False). Of course the 3D model I'm using is not as simple as a sphere.
I would like to add some of the methods I considered using.
Since I am using Python, I thought of using PyMesh, as their intersection feature looked promising. However the list of coordinates I have are not mesh files but just vectors, so it didn't seem to be the appropriate function to use.
I also found this method using ray casting. However, how to do this with PyMesh, or any other Python tool is something I need advice on.
Cast a ray from the 3D point along X-axis and check how many intersections with outer object you find.
Depending on the intersection number on each axis (even or odd) you can understand if your point is inside or outside.
You may want to repeat on Y and Z axes to improve the result (sometimes your ray is coincident with planar faces and intersection number is not reliable).
Converting my comment into an answer for future readers.
You can use a Convex Hull library to check whether a point is inside the hull. Most libraries use signed distance function to determine whether the point is inside. trimesh is one of the libraries that implements this feature.

How to check if a 2D point is inside or outside a 2D Closed Bezier Curve using Python?

Hello,
in my 2d software i have two inputs available:
an array of XY points
[(x,y),(1,1),(2,2),(2,3),(-1,3),...]
and another matrix representing the closed 2D bezier curve handles
[((x,y),(x,y),(x,y)),
((-1,-1),(1,1),(1,2)),
((1,1),(2,2),(2,3)),
...]
How can i check if a point is inside or outside the given curve using python ? using preferably numpy maybe
I don't know how the theory of Bezier curves, so if your second list of points is a kind of compressed way to represent a Bezier curve, first try to sample some points of the curve with the precision you want.
So you have n points of your curve, and then you can apply a simple PIP algorithm : https://en.wikipedia.org/wiki/Point_in_polygon
I can explain in details later if you want to know how to do it programmatically.
I cant write code right here, because I need the entire program to understand properly, however I may provide two approaches how to do that.
The hardest way is to approximate each Bézier curve by a polyline. And then, according to the wiki you can use two techniques:
Ray casting algorithm: the shorthand of the algorithm: You put a ray, which starting from a point and goes through the entire polygon to an another point. Some lines lies inside a polygon, some outside. And then you check to which line belongs a specific point Looks like this:
Winding number algorithm: A little bit about winding numbers. So if a winding number is non-zero, the point lies inside the polygon
The huge drawback of this approach is that the accuracy depends on how close you approximated a curve to a polyline.
The second way is to use a bitmap. For example, you set your points to the white then render the area under the curve to the black and see if your points remain white. This method is more accurate and the fastest one, because you can use the GPU for the render.
And some links related to the first a approach:
https://pomax.github.io/bezierinfo/#intersections
http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node80.html

Is there a way to get matplotlib.path.contains_points to be inclusive of boundary points

We have a hit test use case that wishes to also consider points on the actual boundary of a path. We're using matplotlib.path.contains_points to test a bunch of points en masse and it's working very well for us. Today I discovered it returns false for points on the boundary, in our case the origin (0,0) which is a point on the path.
Is there a way to configure the function call to yield True on boundary points, that is to be inclusive of the boundary? I'm only seeing it support an exclusive test, but according to the documentation there's the other parameters for transform and radius, maybe they have some magic number for pushing the thing to true for boundary points?
contains_points(points, transform=None, radius=0.0) Returns a bool
array which is True if the path contains the corresponding point.
If transform is not None, the path will be transformed before
performing the test.
radius allows the path to be made slightly larger or smaller.
A quick scan of the source code says no. matplotlib isn't really intended for spatial ops; it just has a little bit of support for them just because it's an old codebase with a huge API surface.
I suggest using
shapely, which is built specifically for spatial operations like this one, instead. If you use shapely you can take advantage of object.intersects to handle this.
You can roll your points into a pandas.Series consisting of shapely.Point objects and your polygons (given a sequence of coordinates) into a poly = shapely.Polygon(coordinates) object. Then do something like points_that_intersect = points[points.map(lambda p: poly.intersects(p)]

How to determine and extract surface points of 3D object?

I have a 3D object which is not hollow, so there are many 3D points. How would you determine which of these points of such an object (especially with a very curvaceous surface) are on the surface? I understand how to extract them, but I need either a function somewhat like libraryUNK.surfacePoint... Which I don't know.
Or better an understanding of what is considered to be a surface point, which I don't know either and couldn't (yet) develop (for myself) any proper definition.
I know I can do triangulation to get the surface. But I don't get what to do next, as I will be left now with a set of triangles, some of which are on the surface, some of which are not... but again I have no definition how to consider what's on surface and what is not...
It seems to me that you want to compute the convex hull of your 3D points cloud.
It's not an easy problem, but there's plently of solutions (and algorithms) to do that. One of the efficients one is called "convex hull". There's a ConvexHull function in scipy.spatial.
Here is the details with an example (2D, but it works in any dimension)
http://scipy.github.io/devdocs/generated/scipy.spatial.ConvexHull.html
This function use the QHull library
http://www.qhull.org/
There's plently of ressources on the QHull page. There's also a Wikipedia page (Again, this is not the only method to compute convex hulls, you may want to try others):
https://en.wikipedia.org/wiki/Quickhull
Edit: after re-reading the question, it seems your volume may not be convex. Unfortunately, if it isn't, there's no way to tell whether a point is inside the volume or in the surface without additional informations on the volume or on the points cloud.

Categories