I have an array of points in python making a square lattice. I want to triangulate it like this:
so that the braces alternate in a checkerboard pattern from square to square.
My attempts have been based on deforming it before triangulation. For example, shearing the lattice before triangulating via
xy_skew = np.dstack((xypts[:,0]+ 0.1*xypts[:,1], xypts[:,1]))[0]
tri = scipy.spatial.Delaunay(xy_skew)
TRI = tri.vertices
can give me all 'rightward' diagonals or all 'leftward' diagonals, but I haven't found a deformation that can lead to the desired triangulation.
How can I do this efficiently (for lattices of ~million points)?
If relevant, the indices of my points increase in Y first, then increase in X.
Thanks!
Related
the Wikipedia article about Delaunay Triangulations in d dimensions states as a prerequisite for uniqueness of a triangulation:
It is known that there exists a unique Delaunay triangulation for P if P is a set of points in general position; that is, the affine hull of P is d-dimensional and no set of d + 2 points in P lie on the boundary of a ball whose interior does not intersect P.
Now that I've written my own Delaunay library, I want to be able to verify the uniqueness of the triangulation given its points. Checking the dimensionality of the affine hull can be done easily by calculating the rank of the set. The second part however is way more difficult.
How can I check if d+2 points lie on the boundary of a ball not intersecting with the set and without some gigantic loop over each point? Or is there maybe an alternative way of checking the uniqueness?
I'm using Python with Numpy, however this is more of an theoretical question, thus the language doesn't matter.
Thanks!
For each a simplex of maximal dimension of your triangulation, with d+1 points, you have d+1 neighbor simplices. Two neighbor simplices share d points (forming a simplex themselves). As I do not know if you are familiar with that working in dimension d, let's have a look at dimensions 2 and 3...
In dimension 2, a simplex of maximal dimension is a triangle (simplex of dimension 2), and two neighbor triangles share an edge (simplex of dimension 1).
In dimension 3, a simplex of maximal dimension is a tetrahedron (simplex of dimension 3), and two neighbor tetrahedra share an a face that is a triangle (simplex of dimension 2).
Anyway, given a Delaunay triangulation in dimension d, if you want to check if you have a unique triangulation, iterate on simplices of dimension d-1 (triangles in 3D, or edges in 2D), and take two incident simplices (two neighbor tetrahedra in 3D, or neighbor triangles in 2D). That gives you d+2 points. As the triangulation is Delaunay, you know that the in_sphere predicate for those d+2 points has a result positive or null. If, during the iteration on simplices of dimension d, the result of all the in_sphere predicate for the d+2 points is strictly positive, then your triangulation is unique, otherwise it is degenerated and non-unique.
Have a look at the paper Efficient Exact Geometric Predicates for Delaunay Triangulations by Olivier Devillers and Sylvain Pion: the introduction gives the basics of the theory about Delaunay triangulations, and the in_sphere predicate. It also gives leads to implement the orientation and in_sphere predicates in an exact but efficient way. That might help you in your implementation of the Delaunay triangulations.
You have already a Delaunay triangulation i.e., there are no points inside a circumsphere. Now, e.g., for the 2D case, simply check if you can flip any edge such that it is still a Delaunay triangulation. If not, you have a unique solution. Be aware of the rounding errors of double precision arithmetic.
I am working in a discrete 2D grid of points in which there are "shapes" that I would like to create points outside of. I have been able to identify the vertices of these points and take convex hulls. So far, this leads to this and all is good and well. The purple here is the shape in question and the red line is the convex contour I have computed.
What I would like to do now is create two neighborhoods of points outside this shape. The first one is a set of points directly outside (as close as the grid size will allow), the second is another set of points but offset some distance away (the distance is not fixed, but rather an input).
I have attempted to write this in Python and get okay results. Here is an example of my current output. The problem is I notice the offsets are not perfect, for example look at the bottom most point in the image I attached. It kinks downwards whereas the original shape does not. It's not too bad in this example, but in other cases where the shape is smaller or if I take a smaller offset it gets worse. I also have an issue where the offsets sometimes overlap, even if they are supposed to be some distance away. I would also like there to be one line in each section of the contour, not two lines (for example in the top left).
My current attempt uses the Shapely package to handle most of the computational geometry. An outline of what I do once I have found the vertices of the convex contour is to offset these vertices by some amount, and interpolate along each pair of vertices to obtain many points alone these lines. Afterwards I use a coordinate transform to identify all points to the nearest grid point. This is how I obtain my final set of points. Below is the actual code I have written.
How can I improve this so I don't run into the issues I described?
Function #1 - Computes the offset points
def OutsidePoints(vertices, dist):
poly_line = LinearRing(vertices)
poly_line_offset = poly_line.buffer(dist, resolution=1, join_style=2, mitre_limit=1).exterior
new_vertices = list(poly_line_offset.coords)
new_vertices = np.asarray(new_vertices)
shape = sg.Polygon(new_vertices)
points = []
for t in np.arange(0, shape.length, step_size):
temp_points = np.transpose(shape.exterior.interpolate(t).xy)
points.append(temp_points[0])
points = np.array(points)
points = np.unique(points, axis=0)
return points
Function #2 - Transforming these points into points that are on my grid
def IndexFinder(points):
index_points = invCoordinateTransform(points)
for i in range(len(index_points)):
for j in range(2):
index_points[i][j] = math.floor(index_points[i][j])
index_points = np.unique(index_points, axis=0)
return index_points
Many thanks!
Is there any decent Pythonic way to interpolate in a triangular mesh, or would I need to implement that myself? That is to say, given a (X,Y) point we'll call P, and a mesh (vertices at (X,Y) with value Z, forming triangular facets), estimate the value at P. So that means first find the facet that contains the point, then interpolate - ideally a higher order interpolation than just "linearly between the facet's vertices" (i.e., taking into account the neighboring facets)?
I could implement it myself, but if there's already something available in Python....
(I checked scipy.interpolate, but its "meshes" seem to just be regular point grids. This isn't a grid, it's a true 2D mesh; the vertices can be located anywhere.)
I often use matplotlib.tri for this purpose. Here Xv,Yv are the vertices (or nodes) of the triangles, and Zv the values at those nodes:
from matplotlib.tri import Triangulation, LinearTriInterpolator, CubicTriInterpolator
#you can add keyword triangles here if you have the triangle array, size [Ntri,3]
triObj = Triangulation(Xv,Yv)
#linear interpolation
fz = LinearTriInterpolator(triObj,Zv)
Z = fz(X,Y)
#cubic interpolation
fzc = CubicTriInterpolator(triObj,Zv)
Zc = fz(X,Y)
I am doing my best to replicate the algorithm described here in this paper for making an inpainting algorithm. The idea is to get the contour or edge points of the part of the image that needs to be inpainted. In order to find the most linear point in the region, the orthogonal normal vector is found. On page 6, a short description of the implementation is given.
In our implementation the contour
δΩ of the target region is modelled as a dense list of image point
locations. Given a point p ∈ δΩ, the normal direction np
is computed as follows: i) the positions of the
“control” points of δΩ are filtered via a bi-dimensional Gaussian
kernel and, ii) np is estimated as the unit vector orthogonal to
the line through the preceding and the successive points in the
list.
So it appears that I need to put all these points in a gaussian filter. How do I set up a bi-dimensional Gaussian filter when we have a single dimension or a list of points?
Lets say our contour is a box shape at points, then I create a 1 dimensional list of points: [1,1],[1,2],[1,3],[2,1],[2,3],[3,1],[3,2],[3,3]. Do I need to simply make a new 2d matrix table and put the points in and leave the middle point at [2,2] empty, then run a Gaussian filter on it? This doesn't seem very dense though.
I am trying to run this through python libraries.
a dense list of image points
is simply a line.
You are basically applying a gaussian filter to a black and white image where the line is black and background is white, from what I understand. I think by doing that, they approximate the curve model fitting.
Convolve all of the points in the 2D region surrounding the point and then overwrite the point with the result.
This will make any curve on the edge of the target region less sharp, lowering the noise in the calculation of the normal, which would be the vector orthogonal to the two points that surround the current one.
I have plotted n random points (the black points) and used delaunay triangulation, now I want to interpolate m random evaluation points (the red points) so I need to calculate which triangle the evaluation point is inside.
What is the approach for calculating the vertices of the triangle for each point?
For a given triangle, ABC, a point is inside the triangle if it is on the same side of line AB as point C is, on the same side of line BC as point A is, and on the same side of line AC as point B is. You can pre-optimize this check for each triangle and check them all until you find the triangle(s) it is in. See this page for more details.
To save computation, you can compute the minimum and maximum X and Y coordinates of the points for each triangle. If the X and Y coordinates of a point are not within the minimum and maximum values, you can immediately skip checking that triangle. The point cannot be inside it if it isn't inside the rectangle that bounds the triangle.
I'll assume that triangles do not intersect except of common edges.
You don't want to check every triangle (or subset of them) independently. The main reason is computation errors - due to them you may get answer "inside" for more than one triangle (or zero) which may break logic of your program.
More robust way is:
Find closest edge to the point
Select one of triangles touching this edge
Make one check for that triangle (the point lies on the same side as the third triangle vertex)
If "inside" - return this triangle
If "outside" - return another triangle on this edge (or "nothing" if there is no other triangle)
Even if you will return wrong triangle because of computation error, there still be exactly one triangle and point will lie close enough to it to accept such mistakes.
For #1 you can use something like quad-tree as Michael Wild suggests.
This simple example triangulates 10 random points, a further 3 random points are generated and if they fall inside a triangle the vertices are given:
import numpy as np
from pyhull.delaunay import DelaunayTri
def sign(a,b,c):
return (a[0]-c[0])*(b[1]-c[1])-(b[0]-c[0])*(a[1]-c[1])
def findfacet(p,simplice):
c,b,a = simplice.coords
b1 = sign(p,a,b) < 0.0
b2 = sign(p,b,c) < 0.0
b3 = sign(p,c,a) < 0.0
return b1 == b2 == b3
data = np.random.randn(10, 2)
dtri = DelaunayTri(data)
interpolate = np.random.randn(3, 2)
for point in interpolate:
for triangle in dtri.simplices:
if findfacet(point,triangle):
print "Point",point,"inside",triangle.coords
break
Using matplotlib to visualize (code omitted):
The dotted cyan lines now connect the points to interpolate with the vertices of triangle it lays within. The black lines are the convex hull, and the solid cyan lines are the delaunay triangulation.
A Delaunay triangulation is in itself a search data structure. Your Delaunay triangulation implementation probably has location functions. How have you computed the Delaunay triangulation of your points?
CGAL has an implementation of 2D and 3D triangulations. The resulting data structure is able to localize any point using a walk from a given point. See for example that chapter of the manual. CGAL is a C++ library, but it has python bindings.