{"id":22615405,"url":"https://github.com/stla/qhull","last_synced_at":"2025-10-07T02:46:09.639Z","repository":{"id":47388588,"uuid":"118852133","full_name":"stla/qhull","owner":"stla","description":"Delaunay triangulation, Voronoi diagrams and convex hulls in arbitrary dimension.","archived":false,"fork":false,"pushed_at":"2022-08-08T08:36:14.000Z","size":1148,"stargazers_count":2,"open_issues_count":2,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-20T17:29:29.680Z","etag":null,"topics":["computational-geometry","haskell"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stla.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-25T02:40:29.000Z","updated_at":"2024-11-01T13:31:28.000Z","dependencies_parsed_at":"2022-08-30T10:10:32.974Z","dependency_job_id":null,"html_url":"https://github.com/stla/qhull","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/stla/qhull","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqhull","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqhull/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqhull/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqhull/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stla","download_url":"https://codeload.github.com/stla/qhull/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqhull/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278710922,"owners_count":26032546,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["computational-geometry","haskell"],"created_at":"2024-12-08T19:06:44.454Z","updated_at":"2025-10-07T02:46:09.623Z","avatar_url":"https://github.com/stla.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# qhull\n\nDelaunay triangulation, Voronoi diagrams and convex hulls.\nBased on the `qhull` C library.\n\n## Delaunay tesselation\n\nConsider this list of vertices (actually these are the vertices of a\npolyhedron):\n\n```haskell\nvertices = [\n            [ -5, -5,  16 ]  -- 0\n          , [ -5,  8,   3 ]  -- 1\n          , [  4, -1,   3 ]  -- 2\n          , [  4, -5,   7 ]  -- 3\n          , [  4, -1, -10 ]  -- 4\n          , [  4, -5, -10 ]  -- 5\n          , [ -5,  8, -10 ]  -- 6\n          , [ -5, -5, -10 ]  -- 7\n                           ]\n```\n\nThe `delaunay` function splits the polyhedron into simplices, the tiles of the\ntesselation:\n\n```haskell\n\u003e import Delaunay\n\u003e d \u003c- delaunay vertices False False\n\u003e _tiles d\nfromList\n  [ ( 0\n    , Tile\n        { _simplex =\n            Simplex\n              { _points =\n                  fromList\n                    [ ( 2 , [ 4.0 , -1.0 , 3.0 ] )\n                    , ( 4 , [ 4.0 , -1.0 , -10.0 ] )\n                    , ( 5 , [ 4.0 , -5.0 , -10.0 ] )\n                    , ( 7 , [ -5.0 , -5.0 , -10.0 ] )\n                    ]\n              , _circumcenter =\n                  [ -0.5000000000000009 , -3.0 , -3.499999999999999 ]\n              , _circumradius = 8.154753215150047\n              , _volume = 78.0\n              }\n        , _neighborsIds = fromList [ 1 , 3 ]\n        , _facetsIds = fromList [ 0 , 1 , 2 , 3 ]\n        , _family = Nothing\n        , _toporiented = False\n        }\n    )\n  , ( 1\n    , Tile\n        { _simplex =\n  ......\n```\n\nThe field `_tiles` is a map of `Tile` objects. The keys of the map are\nthe tiles identifiers. A `Tile` object has five fields:\n\n-   `_simplex`, a `Simplex` object;\n\n-   `_neighborsIds`, a set of tiles identifiers, the neighbors of the tile;\n\n-   `facetsIds`, a set of facets identifiers, the facets of the tile;\n\n-   `family`, two tiles of the same family share the same circumcenter;\n\n-   `toporiented`, Boolean, whether the tile is top-oriented.\n\nA `Simplex` object has four fields:\n\n-   `_points`, the vertices of the simplex, actually a map of the vertices\nidentifiers to their coordinates\n\n-   `_circumcenter`, the coordinates of the circumcenter of the simplex;\n\n-   `_circumradius`, the circumradius;\n\n-   `_volume`, the volume of the simplex (the area in dimension 2, the\n  length in dimension 1).\n\nAnother field of the output of `delaunay` is `_tilefacets`:\n\n```haskell\n\u003e _tilefacets d\nfromList\n  [ ( 0\n    , TileFacet\n        { _subsimplex =\n            Simplex\n              { _points =\n                  fromList\n                    [ ( 4 , [ 4.0 , -1.0 , -10.0 ] )\n                    , ( 5 , [ 4.0 , -5.0 , -10.0 ] )\n                    , ( 7 , [ -5.0 , -5.0 , -10.0 ] )\n                    ]\n              , _circumcenter = [ -0.5000000000000009 , -3.0 , -10.0 ]\n              , _circumradius = 4.924428900898053\n              , _volume = 36.0\n              }\n        , _facetOf = fromList [ 0 ]\n        , _normal = [ 0.0 , 0.0 , -1.0 ]\n        , _offset = -10.0\n        }\n    )\n  , ( 1\n    , TileFacet\n        { _subsimplex =\n  ......\n```\n\nThis is a map of `TileFacet` objects. A tile facet is a subsimplex. The keys of\nthe map are the identifiers of the facets.\nA `TileFacet` object has four fields: `_subsimplex`, a `Simplex` object,\n`_facetOf`, the identifiers of the tiles this facet belongs to (a set of one\nor two integers), `_normal`, the normal of the facet, and `offset`, the offset\nof the facet.\n\nFinally, the output of `delaunay` has a `_sites` field, the vertices with\nadditional information:\n\n```haskell\n\u003e _sites d\nfromList\n  [ ( 0\n    , Site\n        { _point = [ -5.0 , -5.0 , 16.0 ]\n        , _neighsitesIds = fromList [ 1 , 3 , 7 ]\n        , _neighfacetsIds = fromList [ 15 , 16 , 17 ]\n        , _neightilesIds = fromList [ 5 ]\n        }\n    )\n  , ( 1\n    , Site\n  ......\n```\n\nThis is a map of `Site` objects. The keys of the map are the identifiers of\nthe vertices. A `Site` object has four fields:\n\n-   `_point`, the coordinates of the vertex;\n\n-   `_neighsitesIds`, the identifiers of the connected vertices;\n\n-   `_neighfacetsIds`, a set of integers, the identifiers of the facets the\nvertex belongs to;\n\n-   `_neightilesIds`, the set of the identifiers of the tiles the vertex belongs\nto.\n\n[![gfycat](https://thumbs.gfycat.com/FreeFaithfulArgali-size_restricted.gif)](https://gfycat.com/FreeFaithfulArgali)\n\n\n## Voronoi diagrams\n\nThe library allows to get the Voronoi diagram of a list of sites (vertices)\nfrom the Delaunay tesselation. Here is a 3D example.\n\n```haskell\ncentricCuboctahedron :: [[Double]]\ncentricCuboctahedron = [[i,j,0] | i \u003c- [-1,1], j \u003c- [-1,1]] ++\n                       [[i,0,j] | i \u003c- [-1,1], j \u003c- [-1,1]] ++\n                       [[0,i,j] | i \u003c- [-1,1], j \u003c- [-1,1]] ++\n                       [[0,0,0]]\nimport Delaunay\nimport Voronoi3D\nd \u003c- delaunay centricCuboctahedron False False\nv = voronoi3 d\n```\n\nIn some circumstances, one has to run the Delaunay tesselation including the\ndegenerate tiles in order to get the correct Voronoi diagram, that is to say\n`delaunay vertices False True`.\n\nThe output of `voronoi3` is a list of Voronoi cells given as pairs, each pair\nconsisting of a site and a list of edges.\nThis is the cell of the center `[0, 0, 0]`:\n\n```haskell\n\u003e last v\n( [ 0.0 , 0.0 , 0.0 ]\n, [ Edge3 ( ( -0.5 , -0.5 , 0.5 ) , ( 0.0 , 0.0 , 1.0 ) )\n  , Edge3 ( ( -0.5 , -0.5 , 0.5 ) , ( 0.0 , -1.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , -0.5 , 0.5 ) , ( -1.0 , 0.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , 0.5 , 0.5 ) , ( 0.0 , 0.0 , 1.0 ) )\n  , Edge3 ( ( -0.5 , 0.5 , 0.5 ) , ( 0.0 , 1.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , 0.5 , 0.5 ) , ( -1.0 , 0.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , -0.5 , 0.5 ) , ( 0.0 , 0.0 , 1.0 ) )\n  , Edge3 ( ( 0.5 , -0.5 , 0.5 ) , ( 0.0 , -1.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , -0.5 , 0.5 ) , ( 1.0 , 0.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , 0.5 , 0.5 ) , ( 0.0 , 0.0 , 1.0 ) )\n  , Edge3 ( ( 0.5 , 0.5 , 0.5 ) , ( 0.0 , 1.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , 0.5 , 0.5 ) , ( 1.0 , 0.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , -0.5 , -0.5 ) , ( 0.0 , 0.0 , -1.0 ) )\n  , Edge3 ( ( -0.5 , -0.5 , -0.5 ) , ( 0.0 , -1.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , -0.5 , -0.5 ) , ( -1.0 , 0.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , 0.5 , -0.5 ) , ( 0.0 , 0.0 , -1.0 ) )\n  , Edge3 ( ( -0.5 , 0.5 , -0.5 ) , ( 0.0 , 1.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , 0.5 , -0.5 ) , ( -1.0 , 0.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , -0.5 , -0.5 ) , ( 0.0 , 0.0 , -1.0 ) )\n  , Edge3 ( ( 0.5 , -0.5 , -0.5 ) , ( 0.0 , -1.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , -0.5 , -0.5 ) , ( 1.0 , 0.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , 0.5 , -0.5 ) , ( 0.0 , 0.0 , -1.0 ) )\n  , Edge3 ( ( 0.5 , 0.5 , -0.5 ) , ( 0.0 , 1.0 , 0.0 ) )\n  , Edge3 ( ( 0.5 , 0.5 , -0.5 ) , ( 1.0 , 0.0 , 0.0 ) )\n  ]\n)\n```\n\nThis is a bounded cell: it has finite edges only. The other ones are not\nbounded, they have infinite edges:\n\n```haskell\n\u003e head v\n( [ -1.0 , -1.0 , 0.0 ]\n, [ Edge3 ( ( -0.5 , -0.5 , 0.5 ) , ( 0.0 , -1.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , -0.5 , 0.5 ) , ( -1.0 , 0.0 , 0.0 ) )\n  , IEdge3\n      ( ( -0.5 , -0.5 , 0.5 )\n      , ( -0.5773502691896258 , -0.5773502691896258 , 0.5773502691896258 )\n      )\n  , Edge3 ( ( -0.5 , -0.5 , -0.5 ) , ( 0.0 , -1.0 , 0.0 ) )\n  , Edge3 ( ( -0.5 , -0.5 , -0.5 ) , ( -1.0 , 0.0 , 0.0 ) )\n  , IEdge3\n      ( ( -0.5 , -0.5 , -0.5 )\n      , ( -0.5773502691896258 , -0.5773502691896258 , -0.5773502691896258 )\n      )\n  , IEdge3 ( ( -1.0 , 0.0 , 0.0 ) , ( 1.0 , 0.0 , 0.0 ) )\n  , IEdge3 ( ( 0.0 , -1.0 , 0.0 ) , ( 0.0 , -1.0 , 0.0 ) )\n  ]\n)\n```\n\n[![gfycat](https://thumbs.gfycat.com/HarmoniousHighlevelBushbaby-size_restricted.gif)](https://gfycat.com/HarmoniousHighlevelBushbaby)\n\n\n## Convex hull\n\nThe `convexHull` function of the `ConvexHull` module generates the convex hull\nof a list of points.\n\n```haskell\nimport ConvexHull\nimport ConvexHull.Examples -- for the function randomInCube\npoints \u003c- randomInCube 100 -- 100 random points in a cube\nhull \u003c- convexHull points False False Nothing\n```\n\nThe vertices of the convex hull are stored in the field `_hvertices`:\n\n```haskell\n\u003e _hvertices hull\nfromList\n  [ ( 3\n    , Vertex\n        { _point =\n            [ 0.7872072051657094 , 0.450772463858757 , 1.9900427529711773e-2 ]\n        , _neighfacets = fromList [ 42 , 43 , 47 , 48 ]\n        , _neighvertices = fromList [ 1 , 11 , 64 , 88 ]\n        , _neighridges = fromList [ 70 , 71 , 72 , 77 ]\n        }\n    )\n  , ( 6\n    , Vertex\n  ......\n```\n\nThe edges in the field `_hedges`:\n\n```haskell\n\u003e _hedges hull\nfromList\n  [ ( Pair 14 70\n    , ( [ 0.9215432980174852 , 0.8554065771602318 , 0.9842902519648512 ]\n      , [ 0.9497713758656887 , 0.998006476041318 , 0.7243639875028591 ]\n      )\n    )\n  , ( Pair 84 99\n  ......\n```\n\nThe facets in the field `_hfacets`:\n\n```haskell\n\u003e _hfacets hull\nfromList\n  [ ( 0\n    , Facet\n        { _fvertices =\n            fromList\n              [ ( 4\n                , [ 1.5757133629105136e-3\n                  , 0.6442797662244039\n                  , 0.7058559215899725\n                  ]\n                )\n              , ( 67\n                , [ 2.7500520534961326e-2\n                  , 0.37516259577251554\n                  , 0.7331611715042575\n                  ]\n                )\n              , ( 77\n                , [ 3.46399386146774e-2\n                  , 5.575911794526589e-2\n                  , 0.46787034305814157\n                  ]\n                )\n              ]\n        , _fridges =\n            fromList\n              [ ( 0\n                , Ridge\n                    { _rvertices =\n                        fromList\n                          [ ( 4\n                            , [ 1.5757133629105136e-3\n                              , 0.6442797662244039\n                              , 0.7058559215899725\n                              ]\n                            )\n                          , ( 77\n                            , [ 3.46399386146774e-2\n                              , 5.575911794526589e-2\n                              , 0.46787034305814157\n                              ]\n                            )\n                          ]\n                    , _ridgeOf = fromList [ 0 , 4 ]\n                    }\n                )\n              , ( 1\n                , Ridge\n                    { _rvertices =\n                        fromList\n                          [ ( 4\n                            , [ 1.5757133629105136e-3\n                              , 0.6442797662244039\n                              , 0.7058559215899725\n                              ]\n                            )\n                          , ( 67\n                            , [ 2.7500520534961326e-2\n                              , 0.37516259577251554\n                              , 0.7331611715042575\n                              ]\n                            )\n                          ]\n                    , _ridgeOf = fromList [ 0 , 2 ]\n                    }\n                )\n              , ( 2\n                , Ridge\n                    { _rvertices =\n                        fromList\n                          [ ( 67\n                            , [ 2.7500520534961326e-2\n                              , 0.37516259577251554\n                              , 0.7331611715042575\n                              ]\n                            )\n                          , ( 77\n                            , [ 3.46399386146774e-2\n                              , 5.575911794526589e-2\n                              , 0.46787034305814157\n                              ]\n                            )\n                          ]\n                    , _ridgeOf = fromList [ 0 , 1 ]\n                    }\n                )\n              ]\n        , _centroid =\n            [ 2.1238724170849748e-2 , 0.3584004933140618 , 0.6356291453841239 ]\n        , _normal =\n            [ -0.9930268604214181\n            , -8.766369712550202e-2\n            , 7.882087723357102e-2\n            ]\n        , _offset = 2.40848904384814e-3\n        , _area = 4.0339144929987907e-2\n        , _neighbors = fromList [ 1 , 2 , 4 ]\n        , _family = None\n        , _fedges =\n            fromList\n              [ ( Pair 4 67\n                , ( [ 1.5757133629105136e-3\n                    , 0.6442797662244039\n                    , 0.7058559215899725\n                    ]\n                  , [ 2.7500520534961326e-2\n                    , 0.37516259577251554\n                    , 0.7331611715042575\n                    ]\n                  )\n                )\n              , ( Pair 67 77\n                , ( [ 2.7500520534961326e-2\n                    , 0.37516259577251554\n                    , 0.7331611715042575\n                    ]\n                  , [ 3.46399386146774e-2\n                    , 5.575911794526589e-2\n                    , 0.46787034305814157\n                    ]\n                  )\n                )\n              , ( Pair 4 77\n                , ( [ 1.5757133629105136e-3\n                    , 0.6442797662244039\n                    , 0.7058559215899725\n                    ]\n                  , [ 3.46399386146774e-2\n                    , 5.575911794526589e-2\n                    , 0.46787034305814157\n                    ]\n                  )\n                )\n              ]\n        }\n    )\n  , ( 1\n    , Facet\n  ......\n```\n\n[![gfycat](https://thumbs.gfycat.com/QuaintUnrulyBlackpanther-size_restricted.gif)](https://gfycat.com/QuaintUnrulyBlackpanther)\n\n\n## Halfspaces intersections\n\n![equation](http://latex.codecogs.com/gif.latex?0%5Cleq%20x%5Cleq%203,%5Cquad%20%200%5Cleq%20y%5Cleq%202-%5Cfrac%7B2%7D%7B3%7Dx,%5Cquad%200%5Cleq%20z%5Cleq%206-2x-3y)\n\n```haskell\nimport HalfSpaces\nimport Data.Ratio ((%))\nx = newVar 1\ny = newVar 2\nz = newVar 3\nconstraints =\n  [ x .\u003e=  0 -- shortcut for x .\u003e=. cst 0\n  , x .\u003c=  3\n  , y .\u003e=  0\n  , y .\u003c=. cst 2 ^-^ (2%3)*^x\n  , z .\u003e=  0\n  , z .\u003c=. cst 6 ^-^ 2*^x ^-^ 3*^y ]\n```\n\n```haskell\n\u003e hsintersections constraints False\n[ [ -1.1102230246251565e-16 , -1.1102230246251565e-16 , 6.0 ]\n, [ 0.0 , 2.0 , 0.0 ]\n, [ 0.0 , 0.0 , 0.0 ]\n, [ 3.0 , 0.0 , 0.0 ] ]\n```\n\n## Gallery\n\nThe convex hull of a curve on the sphere:\n\n![Imgur](https://i.imgur.com/kaS78HG.png)\n\nThe Voronoi cell of a point inside the Utah teapot:\n\n![Imgur](https://i.imgur.com/gmgKDrE.png)\n\nThe Voronoi diagram of a projection of the truncated tesseract:\n\n![Imgur](https://i.imgur.com/mocwfy6.png)\n\nThe Voronoi diagram of a cube surrounded by three perpendicular circles:\n\n![Imgur](https://i.imgur.com/tK4rjhL.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstla%2Fqhull","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstla%2Fqhull","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstla%2Fqhull/lists"}