end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

pyclipper for python による多角形の切り抜き

先日までのentryでは、shapely for python で polygonを操作していましたが、pyclipper もあるらしい。

import pyclipper

from matplotlib.path        import Path
from matplotlib.patches     import PathPatch
from matplotlib.collections import PatchCollection
from shapely.geometry       import Polygon
from xml.dom                import minidom
import matplotlib.pyplot as plt
import numpy             as np

def main():
    clip = [[190, 210], [240, 210], [240, 130], [190, 130]]
    subj = [
        [[180, 200], [260, 200], [260, 150], [180, 150]],
        [[215, 160], [230, 190], [200, 190]] ]
    
    pc = pyclipper.Pyclipper()
    pc.AddPath(clip,  pyclipper.PT_CLIP,    True)
    pc.AddPaths(subj, pyclipper.PT_SUBJECT, True)

    solution = pc.Execute(pyclipper.CT_INTERSECTION,
                          pyclipper.PFT_EVENODD,
                          pyclipper.PFT_EVENODD)
    polygons = []

    fig, ax = plt.subplots()
    polygons.append( Polygon( shell=clip ) )
    polygons.append( Polygon( shell=subj[0], holes=[subj[1]] ) )
    for polygon in polygons:
        plot_polygon(ax, polygon,
                     facecolor='lightgray',
                     edgecolor='black',
                     alpha=0.2)
    polygon = Polygon( shell=solution[0], holes=[solution[1]] )
    plot_polygon(ax, polygon,
                 facecolor='None',
                 edgecolor='red')
    plt.show()

# Plots a Polygon to pyplot `ax`
# cf. https://stackoverflow.com/questions/55522395
def plot_polygon(ax, poly, **kwargs):
    path = Path.make_compound_path(
        Path(np.asarray(poly.exterior.coords)[:, :2]),
        *[Path(np.asarray(ring.coords)[:, :2]) for ring in poly.interiors])

    patch = PathPatch(path, **kwargs)
    collection = PatchCollection([patch], **kwargs)
    
    ax.add_collection(collection, autolim=True)
    ax.autoscale_view()
    return collection


if __name__ == '__main__':
    main()

↑こうかくと、↓こう表示されます