noinia / hgeometry

HGeometry is a library for computing with geometric objects in Haskell. It defines basic geometric types and primitives, and it implements some geometric data structures and algorithms. The main two focusses are: (1) Strong type safety, and (2) implementations of geometric algorithms and data structures that have good asymptotic running time guarantees.
120 stars 40 forks source link
computational-geometry geometric-algorithms geometry haskell

HGeometry

GitHub Workflow Status Hackage API docs coverage

HGeometry is a library for computing with geometric objects such as points, line segments, and polygons, in Haskell. It defines basic geometric types and primitive operations on these types (for example functions to test or compute the intersection of two line segments), and it implements some geometric data structures and algorithms. The main two focusses are:

  1. To provide idiomatic implementations of geometric algorithms and data structures that have good asymptotic running time guarantees, and
  2. Strong type safety.

Please note that first aspect --implementing good algorithms and data structures-- is much of a work in progress. Only a few algorithms have been implemented, and most likely they can use some improvements.

HGeometry Packages

HGeometry currently consists of three packages:

The hgeometry package itself actually consists of several libraries:

Examples

The hgeometry-examples provides some examples of using the library.

Available Geometric Algorithms and Data Structures

This is a brief overview of some of the main available algorithms in HGeometry. Refer to the haddocks for more details. HGeometry contains algorithms for computing

HGeometry also contains an implementation of some geometric data structures. In particular,

Avoiding Floating-point issues

All geometry types are parameterized by a numerical type r. It is well known that Floating-point arithmetic and Geometric algorithms don't go well together; i.e. because of floating point errors one may get completely wrong results. Hence, I strongly advise against using Double or Float for these types.

In most algorithms it is sufficient if the type r is Fractional. Hence, you can use an exact number type such as Data.Ratio.Rational or HGeometry.Number.Real.Rational (which is essentially just a Rational with a friendlier Show instance).

Interval Arithmetic (to speed up our computations) is one of the things on the main things on the TODO list.

Working with additional data

In many applications we do not just have geometric data, e.g. Point d rs or Polygon rs, but instead, these types have some additional properties, like a color, size, thickness, elevation, or whatever. We use typeclasses to make sure it is easy to use the functions with custom geometric types that store such additional fields. For example, the 2d convex hull algorithms have type:

convexHull :: (Ord r, Num r, Point_ point 2 r) => NonEmpty point -> ConvexPolygon point

In many cases you may not want to explicitly declare a new specific point type, but just "attach" an additional value (e.g. a color) to a point. You may want to use the Ext type (typically seen as (:+) from Heometry.Ext in such cases.

Build Instructions

HGeometry heavily relies on typeclasses to support polymorphic inputs. Therefore, if you are using this package, it is recommended to compile your package with GHC options -fspecialise-aggressively -fexpose-all-unfoldings to make sure GHC sufficiently specializes the calls. You can do so by adding the following to your executable/library stanza in your cabal file:

    ghc-options: -fspecialise-aggressively -fexpose-all-unfoldings

Not doing so may significantly impact the performance of your compiled code.