0

I have a shapefile with several contiguous polygons and I want to reduce their number of nodes keeping the adjacent polygons topologically consistent. I was thinking of deleting nodes based on the angle that results from the 2 segments on either side of the node; in particular deleting nodes which form angles <180º and >175º.

I have seen a comment referring to the same idea, but I have very basic knowledge of coding. How could this be implemented in Python?

https://stackoverflow.com/a/2624475/8435715

Adri
  • 1
  • 1
  • Welcome to SO. Please show us your code snippet. – cSteusloff Feb 01 '18 at 12:45
  • Are you asking for an algorithm or for the actual code? Imho you have defined your algorithm already and SO is not a code writing service. So I don't understand, what your question is. – Mr. T Feb 01 '18 at 12:51
  • I understand, sorry, I'm not familiar with this forum and I have a too basic knowledge of coding to implement my algorithm. I'll ask again when if i can manage to write the code. thanks – Adri Feb 02 '18 at 20:14

1 Answers1

0

Here is an example of how you can do that based on two criteria - distance between vertices and the angle you described above:

import numpy as np
def reduce_polygon(polygon, angle_th=0, distance_th=0):

    angle_th_rad = np.deg2rad(angle_th)
    points_removed = [0]
    while len(points_removed):
        points_removed = list()
        for i in range(0, len(polygon)-2, 2):
            v01 = polygon[i-1] - polygon[i]
            v12 = polygon[i] - polygon[i+1]
            d01 = np.linalg.norm(v01)
            d12 = np.linalg.norm(v12)
            if d01 < distance_th and d12 < distance_th:
                points_removed.append(i)
                continue
            angle = np.arccos(np.sum(v01*v12) / (d01 * d12))
                if angle < angle_th_rad:
                    points_removed.append(i)
        polygon = np.delete(polygon, points_removed, axis=0)
    return polygon

example:

from matplotlib import pyplot as plt
from time import time
tic = time()
reduced_polygon = reduce_polygon(original_polygon, angle_th=5, distance_th=4)
toc = time()

plt.figure()
plt.scatter(original_polygon[:, 0], original_polygon[:, 1], c='r', marker='o', s=2)
plt.scatter(reduced_polygon[:, 0], reduced_polygon[:, 1], c='b', marker='x', s=20)
plt.plot(reduced_polygon[:, 0], reduced_polygon[:, 1], c='black', linewidth=1)
plt.show()

print(f'original_polygon length: {len(original_polygon)}\n', 
      f'reduced_polygon length: {len(reduced_polygon)}\n'
      f'running time: {round(toc - tic, 4)} secends')

Produces the following result: enter image description here

Amit Oved
  • 79
  • 6