简体   繁体   中英

Constructing convex hull object with known triangular faces

TLDR: I need to construct a python object for fast interior point testing, similar to a SciPy ConvexHull or DelaunayTriangulation . The catch is that I know ahead of time the order in which the triangulation of the points must be constructed: (6 points, 8 triangular faces, with a specific ordering of each face). In effect, I already know what the convex hull should be, but I need it in a form that I can use with existing (and optimised.) libraries (eg Scipy spatial)? How can I do this?

Context: I need to construct a triangular prism (imagine a Toblerone bar - 2 end faces, 6 side faces, all triangular) in order to do some interior point testing. As I will have many such prisms lying adjacent to each other (adjacent on their side faces, imagine many Toblerone bars stood on their ends and next to each other), I need to be careful to ensure that no region in space is contained by two adjacent prisms. The cross section of the prism will not generally be uniform, hence the possibility of overlap between adjacent prisms, as illustrated by this diagram of the approximately planar face between two adjacent prisms:

 ____
|\  /|
| \/ |
| /\ | 
|/__\|

Note the two different diagonals constructed along the face - this is the problem. One prism may split the face into two triangles using the \ diagonal, and the neighbouring prism may instead use the /. In order to ensure no overlap between adjacent prisms, I need to explicitly control the order in which the triangles are formed so that they always use the same diagonal. This I can do: for each prism that I need to construct, I know ahead of time in what order the triangular faces should be constructed. Here's an illustration of two adjacent prisms, with the correct shared diagonal between them: neighbouring prisms, shared diagonal

My issue is with performing fast interior point testing with these prisms. Previously, I was using the approach linked in this answer : Delaunay(prism_points).find_simplex(test_points) >= 0 . It's quick because it is using highly optimised library code, but I have no control over the construction of the triangulation, so there could be overlap.

If I construct the hulls as explicit np.array objects (vertices, faces) then I can use my own code to do the tests (there are numerous possible approaches, I'm projecting rays and testing for intersection with each triangular face). The problem is that this is around ~100x slower than the find_simplex() approach mentioned earlier. Whilst I'm sure I could get the code a bit quicker, it is worth pointing out this code is already fairly optimised from another use case with Cython - I am not sure if I can find all the extra speed I need here. As for the inevitable "do you really need the speed question", please take my word for it. This is turning a 5 minute job into many hours.

What I need is to construct an object I can use with external optimised libraries, whilst retaining control of the triangular faces. Adding extra Cython to my code is of course an option, but which such highly optimised code already out there, using that would be vastly preferable.

Thanks to anyone that can help.

Half a solution... Not an exact solution to the original question, but a different way of achieving the same outcome. Any triangular prism can be split into exactly three tetrahedra (see http://www.alecjacobson.com/weblog/?p=1888 ). This is a specific case of the fact that any polyhedron may be split into tetrahedra by connecting all faces to one vertex, if the faces does not already include it.

Knowing exactly how I would like the face triangles of my prism to be arranged, I can work out what three tetrahedra would reproduce the same configuration of triangles (with extra faces of course being added inside the original prism itself). I then form Delaunay triangulations around each of these three tetrahedra (ie, collections of 4 points) in turn and perform the original interior point tests: if it matches on any then I have a positive result for the whole prism. The key point is that by only giving four points to the Delaunay constructor at a time, I know exactly what triangulation it will return as there is only one way of forming such a tetrahedra (assuming no geometric degeneracy).

It's a bit longwinded, and involves 3x as many tests as I would like, but it's a start. If anyone in the future does know how I could do this better please do let me know.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM