Skip to main content

CGAL's visibility polygons in Python

Project description

pyvispoly

This package provides a Python interface to the CGAL library for computing visibility polygons. It is exact, but not necessarily efficient.

Motivation: This package was developed in the context of implementing an exact solver for the dispersive Art Gallery Problem (see here). Because the problem is difficult and only reasonably small instances can be solved, the focus of this package is on correctness and not on efficiency.

Visibility Polygon

Installation

You can install the package using pip:

pip install --verbose .

or directly via PyPI:

pip install --verbose pyvispoly

During installation, it will download and install CGAL and its dependencies. This may take a while. This requires a C++-compiler to be installed on your system.

:info: On installation problems, please first check out skbuild-conan's troubleshooting guide. It is likely that the automatic C++-compilation fails.

Addressing the Complexity of Visibility Polygon Computation

Computing visibility polygons demands precise arithmetic; imprecise calculations often yield incorrect results. This package leverages the robustness of the CGAL library for accurate visibility polygon computation. Note that it is essential to convert your coordinates to CGAL's exact number type. Failure to use the correct types may result in exceptions.

This package explicitly avoids duck typing and automatic type conversion. While these features could simplify usage, they risk obscuring underlying errors in your code. In geometric computations, precision is paramount; thus, Python's native floating-point numbers are unsuitable.

Usage

# import elements from pyvispoly
from pyvispoly import (
    FieldNumber,
    Point,
    Polygon,
    PolygonWithHoles,
    VisibilityPolygonCalculator,
    plot_polygon,
)
import matplotlib.pyplot as plt
# exact number type
a = FieldNumber(100)
b = FieldNumber(200)
c = a + b
assert isinstance(c, FieldNumber)
print("c:", c)
print("float(c):", float(c))
assert float(c) == 300.0
c: 300.000000
float(c): 300.0
# point type
p1 = Point(FieldNumber(0), FieldNumber(0))
assert p1.x() == FieldNumber(0) and p1.y() == FieldNumber(0)
p2 = Point(2, 3)
p3 = Point(4.0, 5.0)
print("p1:", p1)
print("p2:", p2)
print("p3:", p3)
p1: (0, 0)
p2: (2, 3)
p3: (4, 5)
# Polygon
poly1 = Polygon([Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)])
assert poly1.is_simple()
assert poly1.area() == FieldNumber(1)
assert float(poly1.area()) == 1.0
# The ccw order of the points is important
poly1 = Polygon([Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)][::-1])
assert poly1.is_simple()
assert poly1.area() == FieldNumber(-1)
assert float(poly1.area()) == -1.0
# Polygon with holes
poly2 = PolygonWithHoles(
    [Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)],
    [
        [Point(0.25, 0.25), Point(0.75, 0.25), Point(0.75, 0.75), Point(0.25, 0.75)][
            ::-1
        ]
    ],
)
# boundary is counter-clockwise
assert poly2.outer_boundary().area() >= FieldNumber(0)
for hole in poly2.holes():
    # holes are clockwise
    assert hole.area() <= FieldNumber(0)

fig, ax = plt.subplots()
ax.set_aspect("equal")
plot_polygon(poly2, ax=ax)
plt.show()

png

# set operations on polygons
poly3 = PolygonWithHoles([Point(0, 0), Point(0.1, 0), Point(0.1, 0.1), Point(0, 0.1)])
poly4_list = poly2.difference(poly3)
assert len(poly4_list) == 1, "Expect a single polygon"
poly4 = poly4_list[0]
fig, ax = plt.subplots()
ax.set_aspect("equal")
plot_polygon(poly4, ax=ax)
plt.show()

png

# compute visibility polygon
visp_poly_calc = VisibilityPolygonCalculator(poly4)
vis_poly = visp_poly_calc.compute_visibility_polygon(Point(0.2, 0.0))

fig, ax = plt.subplots()
ax.set_aspect("equal")
plt.title("Visibility Polygon")
plot_polygon(poly4, ax=ax, color="lightgrey")
plot_polygon(vis_poly, ax=ax, color="red", alpha=0.5)
plt.plot([0.2], [0.0], "x", color="black")
plt.savefig("../docs/figures/visibility_polygon.png")
plt.show()

png

# getting some interior points
fig, ax = plt.subplots()
ax.set_aspect("equal")
plt.title("Sample points in the interior")
plot_polygon(poly4, ax=ax, color="lightgrey")
plot_polygon(vis_poly, ax=ax, color="red", alpha=0.5)
plt.plot([0.2], [0.0], "x", color="black")
interior_points = vis_poly.interior_sample_points()
for p in interior_points:
    assert vis_poly.contains(p), "all points should be inside the visibility polygon"
plt.plot(
    [p.x() for p in interior_points],
    [p.y() for p in interior_points],
    "+",
    color="black",
)
plt.show()

png

:warning: The library may segfault if you pass bad polygons. For example, if holes intersect the outer boundary, the library may crash. One could probably catch these errors, but I have not implemented this yet (feel free to do so and submit a pull request).

License

This library incorporates components from the CGAL library through static linking, which are subject to the terms of the GNU General Public License (GPL). Consequently, the use and distribution of this library are also governed by the GPL.

However, if you possess a specialized (commercial) license for CGAL (or replace CGAL), then the portions of this library excluding the CGAL component are available under the more permissive MIT license, consistent with the licensing of my other code.

Please ensure you understand the implications of these licenses before using or distributing this library.

Changelog

  • 0.3.1 Using CGAL6
  • 0.3.0 Added do_intersect.
  • 0.2.0 Made the library more robust and added a repair-method as the boolean operations are not always guaranteed to produce valid polygons. Note that this is just kind of a hack and may not always work.
  • 0.1.3: (2023-11-29) Workaround to bug in CGAL.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyvispoly-0.3.1.tar.gz (171.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyvispoly-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (867.7 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl (922.7 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ i686

pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (832.6 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

pyvispoly-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (867.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl (922.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ i686

pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (832.5 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

pyvispoly-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (868.1 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl (923.4 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ i686

pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (832.7 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

File details

Details for the file pyvispoly-0.3.1.tar.gz.

File metadata

  • Download URL: pyvispoly-0.3.1.tar.gz
  • Upload date:
  • Size: 171.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pyvispoly-0.3.1.tar.gz
Algorithm Hash digest
SHA256 f4684e739a4cc61d22e65de66dd61c939e795cca0ca8dc21e754c9304cc71a2e
MD5 6e3942516265b9d6292f4f7f7140afd5
BLAKE2b-256 1605e1e5178bf61c1b3ce08df4fcdd08c6449261e7482afdad5a884e8ded2f1b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1.tar.gz:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 74d6f121d2c3cecfade5338f9e5e8b3183e2472dde5900ea41b900364a028c5b
MD5 325b28ff467d3eff22044a397855d6e0
BLAKE2b-256 37f5e0addc8455d1f5ee972c7292c57f2d97dfbae651233361b4bde6f7574df1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 66620744758de544e599e267a0b761f97121925789d5ee8f068484bdeabfaa86
MD5 41fe4367b9c9fbb367b7e9f9de3fbc51
BLAKE2b-256 a3da91a7d723b8beb8aa5fbfcc563e9da00e2362ff2da13e77dfa55d51e5a35f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4f94eb92003e84044a287b8a0b4a979e605f07fd709838039a698de70fae4dd4
MD5 a5973041a238ab9c359ab5b3a904ef05
BLAKE2b-256 f8114d63a74eee00d742c8aba78f804f47656c58515ea2846cf36d2bbf1f8dd3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d2f1a3106ec5e6cc721b0bdda46b62864660410cbd56ccc3bd6ebda2e8ff1394
MD5 bcb1006f9cc19e860d8af15a3f27629e
BLAKE2b-256 245c098ce949e6687b8e9071c239abea4f74a17f49d33c41cc399a05a08a3961

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 165ab439b1648669891036b3fa0c46d8f13c43705e456ec82dad3f7081d323b7
MD5 05c256c734e40da325f66db626fc9381
BLAKE2b-256 60719e78fcaaf1fdf73ee8ed4c96ee9bb85a0178c25b6e43df557e000d102d76

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 bc6332332c4045cc35fbf033956504733671dbe8c9a857da29266df7debd0f8e
MD5 63b406422e14a020b0479b5f530f1c37
BLAKE2b-256 4ebd47e2de4e65265042a1a0ee343c1a36d575673e5a8f56d6625c19ff9436f9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e51b8559523e4ef3d96fd605ba2cca842c3f62e2810723f9ab0100119a11b28e
MD5 f3f8478f234e3017e902ab0b70c11fd9
BLAKE2b-256 58f6892e074911c60e9d04c774b1a61f6d967c9f36b30cdf6645d3e2d3c86623

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 072e915a00686c5fba82d20c78e3825fff99c87ac1f96824693b82ee01c7be0c
MD5 481900dcecaa2e182e308439dffac0b3
BLAKE2b-256 b1dc2e05cc9114b3ae165de35df8606a82e5cf925356dcfaf31b75f1636c3d45

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e748bb6dd31faf5893f950aa70626fcb40f6e61db5451cc3f6a2fe71387b0730
MD5 4d2f3ae5a9d8e3aa573c7d42c37295b3
BLAKE2b-256 d2aaace30204d97b63fbf6f96ca39656b42537486c545b9ec20286efa1baee19

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvispoly-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on d-krupke/pyvispoly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page