Background: I work in the upper half-space interpreted as the model of the hyperbolic space. I want to draw a number of hyperbolic polygons (for simplicity, triangles) having vertices on the boundary. In practice, this means two types of shapes:
- (a) triangle with all three vertices in the $xy$ plane, which is part of a sphere such that its center is in the $xy$ plane and it passes through these three vertices (for simplicity, they are always given in the counterclockwise order), which is bounded by the three vertical planes passing through each pair of vertices (
triangle
); - (b) triangle with two vertices in the $xy$ plane and one vertex at the infinity, which is a vertical rectangle (sic) of some fixed height with two specified vertices (for simplicity, having both $x$ and $y$ coordinates different from each other) with a half-disk cut from it (the center of the disk is the midpoint between the vertices, and the circle bounding the disk passes through them) (
triangleInf
).
I am only interested in the case when the projections of all triangles of type (a) onto the $xy$ plane do not intersect each other and together tessellate a certain connected polygon on the plane, and the projections of the triangles of type (b) are the sides of that polygon (which is not the case for the example below).
I implemented the functions which construct these shapes as shown below. One function uses Graphics3D[Sphere[...], ClipPlanes -> ...]
and the other uses ContourPlot3D[..., RegionFunction -> ...]
, but this difference doesn't seem to be relevant to the question. Also, I believe I can implement triangleInf
using only Polygon
by discretizing the boundary. But implementing triangle
without ClipPlanes
seems much more tricky.
So I made this:
height = 1.5;
triangleInf[{v1_, v2_}] :=
Module[{u1 = {Sequence @@ v1, 0}, u2 = {Sequence @@ v2, 0}, c, r2, xx = First /@ {v1, v2}, yy = Last /@ {v1, v2}},
c = (u1 + u2)/2; r2 = SquaredEuclideanDistance[u1, c];
ContourPlot3D[({x, y} - v2).Cross[v1 - v2] == 0, {x, Min@xx, Max@xx}, {y, Min@yy, Max@yy}, {z, 0, height},
RegionFunction -> (SquaredEuclideanDistance[{#1, #2, #3}, c] > r2 &), RegionBoundaryStyle -> None, Mesh -> None, BoxRatios -> Automatic]
];
planes[{v1_, v2_, v3_}] := Append[InfinitePlane /@ {{v1, v2, v2 + {0, 0, 1}}, {v2, v3, v3 + {0, 0, 1}}, {v3, v1, v1 + {0, 0, 1}}}, InfinitePlane[{{0, 0, 0}, {1, 0, 0}, {0, 1, 0}}]];
triangle[vertices_] := Module[{cx, cy, r},
{{cx, cy}, r} = List @@ CircleThrough[vertices];
Graphics3D[Sphere[{cx, cy, 0}, r],
ClipPlanes -> planes[{Sequence @@ #, 0} & /@ vertices]]
];
tf = triangle[{{0, 0}, {1, 1}, {1, 0}}]
tf2 = triangle[{{0, 0}, {1, 0}, {1, -1}}]
ti = triangleInf[{{1/2, 1/2}, {-1, -1}}]
Show[tf, tf2, ti, Axes -> True, AxesLabel -> {"x", "y", "z"},
PlotRange -> {{-1, 1}, {-1, 1}, {0, 2}}]
Each function on its own does what I want. However I want all these shapes to be shown together. And when I combine them using Show
, the ClipPlanes
option seems to be inherited from the first graphics3d object, and I don't know how to prevent it.
How do I combine multiple plots which use ClipPlanes
?
Or, possibly I can work around this issue by implementing triangle
without ClipPlanes
?