I'm fairly new to Mathematica (and programming in general tbh) and need this for a math project I'm working on.
I generate large collections of (rational, 2d) points and need to find which of these points are the vertices of the convex hull.
Some googling suggested that MeshCoordinates
would do this, but it does not exclude points on the edges of the convex hull that are collinear with the vertices. It also gives rounded decimals but that is less of an issue.
Is there a simple way to do this?
Edit to include a simplified example, the vertices of the unit square with a redundant point ({1, .5}
):
pts = {{0, 0}, {1, 0}, {0, 1}, {1, 1}, {1, .5}}
Both MeshCoordinates[ConvexHullMesh[pts]]
and ConvexHullMesh[pts]["VertexCoordinates"]
return the point {1, .5}
, which is clearly not a vertex of the unit square.
The points I'm generating are not random, they are the result of a fairly involved set of calculations and many of them can be collinear.
Answer
Update: a brute force approach to eliminate coordinates that lie in the convex hull of other coordinates:
ClearAll[noncollinearF]
noncollinearF[verts_]:= Function[{k}, Nor @@ (RegionMember[ConvexHullMesh[#],k]&/@
Subsets[Complement[verts,{k}],{2}])]
Pick[#, noncollinearF[#] /@ #]&[Rationalize @ ConvexHullMesh[pts]["VertexCoordinates"]]
{{0, 0}, {1, 0}, {0, 1}, {1, 1}}
Pick[#, noncollinearF[#] /@ #]&[Rationalize@ConvexHullMesh[pts2]["VertexCoordinates"]]
{{0, 0}, {1, 1}, {1, 0}, {2, 1}}
Or define a function that picks the non-collinear vertices of the convex hull of a set of 2D points:
ncvF = With[{v = #}, Pick[v, Function[{k}, Nor @@ (RegionMember[ConvexHullMesh[#],k]&/@
Subsets[Complement[v,{k}],{2}])]/@v]]&;
ncvF[pts]
{{0, 0}, {1, 0}, {0, 1}, {1, 1}}
ncvF[pts2]
{{0, 0}, {1, 1}, {1, 0}, {2, 1}}
Previous post:
The function Geometry`ConvexHull2
gives the desired coordinates for the simple example:
pts = {{0, 0}, {1, 0}, {0, 1}, {1, 1}, {1,1/2}};
chm = ConvexHullMesh[pts];
vertices = Rationalize[chm["VertexCoordinates"]] (* or MeshCoordinates[chm] *)
{{0, 0}, {1, 0}, {0, 1}, {1, 1}, {1, 1/2}}
strictvertices = Rationalize[Geometry`ConvexHull2[ pts]]
{{0, 0}, {1, 0}, {1, 1}, {0, 1}}
Show[chm, Graphics@Point[pts], Graphics[{Red, PointSize[Large], Point @ vertices}]]
Show[chm, Graphics@Point[pts], Graphics[{Red, PointSize[Large], Point @ strictvertices}]]
... but, it fails to eliminate some coordinates in an other example:
pts2 = {{0, 0}, {1/2, 0}, {1/2, 1/2}, {1, 1}, {3/2, 1}, {1, 0}, {2, 1}, {3/2, 1/2}}
Show[ConvexHullMesh[pts2], Graphics @ Point[pts2],
Graphics[{Red, PointSize[Large], Point @ Geometry`ConvexHull2[ pts2]}]]
Comments
Post a Comment