Here's a solution for your example. However, I don't think this can be easily generalized to n-dimensions.
How it works:
Start with the holes in rows. Convert vertex list to array and use lexicographic ordering to sort the rows.
import numpy as np
import matplotlib.pyplot as plt
coords = np.asarray(
[(1000,3.5), (1000,4.0), (1000,4.5), (1000,5.0), (1000,5.5),
(1100,4.5), (1100, 6.5), (1200,4.0), (1200,5.5), (1200,7.0), (1200,5.5),
(1300,3.5), (1300,4.0), (1300,4.5), (1300, 5.5), (1700,5.0) ])
coords = coords[ np.lexsort(( coords[:,1], coords[:,0] )),:]
Determine grid size as the minimum difference between to vertices that is not zero.
diffs = np.diff(coords, axis = 0)
dx = np.min(diffs[diffs[:,0] > 0.0, 0])
dy = np.min(diffs[diffs[:,1] > 0.0, 1])
The grid contains holes where there is no change in the x-coordinate and the change in the y-coordinate is larger than dy
.
indices = (diffs[:,0] == 0.0) * (diffs[:,1] > dy)
Expand the holes to list of missing grid points using their indices to extract the starting point and the length of the hole. Finally, concatenate
into numpy.array
or return empty array if there is no hole.
hole_list = [ np.asarray( [ [x, y] for y in np.arange( y + dy, y + Dy, dy )] )
for ((x, y), Dy) in zip ( coords[indices,:],
diffs[indices,1] ) ]
if len( hole_list ) > 0:
holes_x = np.concatenate( hole_list )
else:
holes_x = np.asarray( [] )
Now add the found holes to the grid and look for holes in columns. Only have to switch order of lexicographic ordering and add the holes in the rows to avoid finding them twice.
# Holes in columns.
coords_x = np.append( coords, holes_x, axis = 0 )
coords_x = coords[ np.lexsort( ( coords[:,0], coords[:,1] ) ), : ]
diffs = np.diff( coords_x, axis = 0 )
indices = ( diffs[:,1] == 0.0 ) * ( diffs[:,0] > dx )
hole_list = [ np.asarray( [ [x, y] for x in np.arange( x + dx, x + Dx, dx )] )
for ((x, y), Dx) in zip ( coords_x[indices,:],
diffs[indices,0] ) ]
if len( hole_list ) > 0:
holes_y = np.concatenate( hole_list )
else:
holes_y = np.asarray( [] )
Example:
import numpy as np
import matplotlib.pyplot as plt
coords = np.asarray(
[(1000,3.5), (1000,4.0), (1000,4.5), (1000,5.0), (1000,5.5),
(1100,4.5), (1100, 6.5), (1200,4.0), (1200,5.5), (1200,7.0), (1200,5.5),
(1300,3.5), (1300,4.0), (1300,4.5), (1300, 5.5), (1700,5.0) ])
coords = coords[ np.lexsort(( coords[:,1], coords[:,0] )),:]
# Find x and y grid sizes.
diffs = np.diff(coords, axis = 0)
dx = np.min(diffs[diffs[:,0] > 0.0, 0])
dy = np.min(diffs[diffs[:,1] > 0.0, 1])
# Holes in rows.
indices = (diffs[:,0] == 0.0) * (diffs[:,1] > dy)
hole_list = [ np.asarray( [ [x, y] for y in np.arange( y + dy, y + Dy, dy )] )
for ((x, y), Dy) in zip ( coords[indices,:],
diffs[indices,1] ) ]
if len( hole_list ) > 0:
holes_x = np.concatenate( hole_list )
else:
holes_x = np.asarray( [] )
# Holes in columns.
coords_x = np.append( coords, holes_x, axis = 0 )
coords_x = coords[ np.lexsort( ( coords[:,0], coords[:,1] ) ), : ]
diffs = np.diff( coords_x, axis = 0 )
indices = ( diffs[:,1] == 0.0 ) * ( diffs[:,0] > dx )
hole_list = [ np.asarray( [ [x, y] for x in np.arange( x + dx, x + Dx, dx )] )
for ((x, y), Dx) in zip ( coords_x[indices,:],
diffs[indices,0] ) ]
if len( hole_list ) > 0:
holes_y = np.concatenate( hole_list )
else:
holes_y = np.asarray( [] )
# Plot holes.
f = plt.figure()
ax = f.add_subplot(111)
ax.scatter( coords[:,0], coords[:,1], c = 'g', s=200 )
ax.scatter( holes_x[:,0], holes_x[:,1], c = 'r', s=50 )
ax.scatter( holes_y[:,0], holes_y[:,1], c = 'b', s=50 )