Like always, I am probably over complicating this and there is a much simpler way to derive a general formula using built-in Mathematica functions, think about it differently, or a faster way to solve the equation in step 9 below. But having a fairly simple solution to this problem in Mathematica would mean being able to solve many problems on Mathematica Stack Exchange and Math Stack Exchange. And I think an imperative approach is probably not best.
So, if we have a specific convex polyhedron in space (so the exact starting coordinates matter) that is rotated by the RollPitchYawMatrix in Mathematica, and take the orthographic projection into the xy-plane, we always have a formula for the area of the silhouette of the form of a piecewise function:
$$ silhouetteArea = \begin{cases} \sum_{shownface|(\alpha, \beta, \gamma)}^{numShownFaces|(\alpha, \beta, \gamma)} (shownFaceArea*TrigProd(\alpha, \beta, \gamma)), & \text{ if $a_{i} \le \alpha \le a_{f}, b_{i} \le \beta \le b_{f}, c_{i} \le \gamma \le c_{f}$}, ... \end{cases} $$, where each case is a sum of the area of the shadow of the faces in the xy-plane with a domain of angles, where each angle can take a value from $[-2\pi, 2\pi]$.
The main problem is finding which faces show up at which angles, which makes the solution complicated.
So, here is my algorithm that I thought of:
- Create a random convex polyhedron.
- Extract and name the vertex coordinates of the random convex polyhedron.
- Extract and name the faces with corresponding groups the vertices.
- Order the points of each face in a clockwise or counterclockwise manner.
- Use the shoelace theorem to find the area formula of each of the polygons using the names of the vertices instead of the actual coordinates.
- Calculate the centroid of the random convex polyhedron and each face.
- Find each of the normal vectors of each of the faces of the polygon going through the centroid of the polyhedron of the polyhedron and face with it pointing out.
- Apply the rotation matrix, RollPitchYawMatrix[], to each of the face's normal vectors.
- Since we are concerned about the shape projected onto the xy-plane, we only need to look at the faces whose normal vectors have a positive z-coordinate for its normal vector after applying the rotation. But finding the boundary conditions for this is also very difficult Which kind of circles back to our original problem.
- Once we have the $\alpha, \beta, \gamma$-boundaries for which faces show, then use that to create our formula.
This is an example of a possible datum structure at the end of step 3:
exampleDatumStructure=
{
{
{
{{-1.1135163644116066`,0.8090169943749475`,-0.2628655560595668`},"V1"},
{{-0.6881909602355868`,0.5`,-1.1135163644116066`},"V2"},
{{-0.6881909602355868`,-0.5`,-1.1135163644116066`},"V3"},
{{-1.1135163644116066`,-0.8090169943749475`,-0.2628655560595668`},"V4"},
{{-1.3763819204711736`,0.`,0.2628655560595668`},"V5"}
},"F1"},
{
{
{{1.3763819204711736`,0.`,-0.2628655560595668`},"V6"},
{{1.1135163644116066`,0.8090169943749475`,0.2628655560595668`},"V7"},
{{0.6881909602355868`,0.5`,1.1135163644116066`},"V8"},
{{0.6881909602355868`,-0.5`,1.1135163644116066`},"V9"},
{{1.1135163644116066`,-0.8090169943749475`,0.2628655560595668`},"V10"}
},"F2"},
{
{
{{1.1135163644116066`,-0.8090169943749475`,0.2628655560595668`},"V10"},
{{0.6881909602355868`,-0.5`,1.1135163644116066`},"V9"},
{{-0.2628655560595668`,-0.8090169943749475`,1.1135163644116066`},"V11"},
{{-0.42532540417602`,-1.3090169943749475`,0.2628655560595668`},"V12"},
{{0.42532540417601994`,-1.3090169943749475`,-0.2628655560595668`},"V13"}
},"F3"},
{
{
{{0.6881909602355868`,-0.5`,1.1135163644116066`},"V9"},
{{0.6881909602355868`,0.5`,1.1135163644116066`},"V8"},
{{-0.2628655560595668`,0.8090169943749475`,1.1135163644116066`},"V14"},
{{-0.85065080835204`,0.`,1.1135163644116066`},"V15"},
{{-0.2628655560595668`,-0.8090169943749475`,1.1135163644116066`},"V11"}
},"F4"},
{
{
{{0.6881909602355868`,0.5`,1.1135163644116066`},"V8"},
{{1.1135163644116066`,0.8090169943749475`,0.2628655560595668`},"V7"},
{{0.42532540417601994`,1.3090169943749475`,-0.2628655560595668`},"V16"},
{{-0.42532540417602`,1.3090169943749475`,0.2628655560595668`},"V17"},
{{-0.2628655560595668`,0.8090169943749475`,1.1135163644116066`},"V14"}
},"F5"},
{
{
{{1.1135163644116066`,0.8090169943749475`,0.2628655560595668`},"V7"},
{{1.3763819204711736`,0.`,-0.2628655560595668`},"V6"},
{{0.85065080835204`,0.`,-1.1135163644116066`},"V18"},
{{0.2628655560595668`,0.8090169943749475`,-1.1135163644116066`},"V19"},
{{0.42532540417601994`,1.3090169943749475`,-0.2628655560595668`},"V16"}
},"F6"},
{
{
{{1.3763819204711736`,0.`,-0.2628655560595668`},"V6"},
{{1.1135163644116066`,-0.8090169943749475`,0.2628655560595668`},"V10"},
{{0.42532540417601994`,-1.3090169943749475`,-0.2628655560595668`},"V13"},
{{0.2628655560595668`,-0.8090169943749475`,-1.1135163644116066`},"V20"},
{{0.85065080835204`,0.`,-1.1135163644116066`},"V18"}
},"F7"},
{
{
{{-0.42532540417602`,1.3090169943749475`,0.2628655560595668`},"V17"},
{{0.42532540417601994`,1.3090169943749475`,-0.2628655560595668`},"V16"},
{{0.2628655560595668`,0.8090169943749475`,-1.1135163644116066`},"V19"},
{{-0.6881909602355868`,0.5`,-1.1135163644116066`},"V2"},
{{-1.1135163644116066`,0.8090169943749475`,-0.2628655560595668`},"V1"}
},"F8"},
{
{
{{0.2628655560595668`,0.8090169943749475`,-1.1135163644116066`},"V19"},
{{0.85065080835204`,0.`,-1.1135163644116066`},"V18"},
{{0.2628655560595668`,-0.8090169943749475`,-1.1135163644116066`},"V20"},
{{-0.6881909602355868`,-0.5`,-1.1135163644116066`},"V3"},
{{-0.6881909602355868`,0.5`,-1.1135163644116066`},"V2"}
},"F9"},
{
{
{{0.2628655560595668`,-0.8090169943749475`,-1.1135163644116066`},"V20"},
{{0.42532540417601994`,-1.3090169943749475`,-0.2628655560595668`},"V13"},
{{-0.42532540417602`,-1.3090169943749475`,0.2628655560595668`},"V12"},
{{-1.1135163644116066`,-0.8090169943749475`,-0.2628655560595668`},"V4"},
{{-0.6881909602355868`,-0.5`,-1.1135163644116066`},"V3"}
},"F10"},
{
{
{{-0.42532540417602`,-1.3090169943749475`,0.2628655560595668`},"V12"},
{{-0.2628655560595668`,-0.8090169943749475`,1.1135163644116066`},"V11"},
{{-0.85065080835204`,0.`,1.1135163644116066`},"V15"},
{{-1.3763819204711736`,0.`,0.2628655560595668`},"V5"},
{{-1.1135163644116066`,-0.8090169943749475`,-0.2628655560595668`},"V4"}
},"F11"},
{
{
{{-0.85065080835204`,0.`,1.1135163644116066`},"V15"},
{{-0.2628655560595668`,0.8090169943749475`,1.1135163644116066`},"V14"},
{{-0.42532540417602`,1.3090169943749475`,0.2628655560595668`},"V17"},
{{-1.1135163644116066`,0.8090169943749475`,-0.2628655560595668`},"V1"},
{{-1.3763819204711736`,0.`,0.2628655560595668`},"V5"}
},"F12"}
};
Ordering the vertices can be done by modifying this.
And the centroid and normals can be calculated by modifying these:
centroid = Mean[Flatten[vertices, 1]]
(* Function to compute normal for a face *)
getNormal[face_] :=
Module[{A, B, C, normal, directionToCentroid},
{A, B, C} = face[[1 ;; 3, 1]];
normal = Cross[B - A, C - A];
directionToCentroid = centroid - A;
(* Ensure the normal points outward *)
If[Dot[normal, directionToCentroid] > 0,
normal = -normal];
normal
]
(* Compute normals for all faces *)
normals = getNormal /@ exampleDatumStructure[[All, 1]];
But I have a strong hunch that there is a simpler answer out there that does not use any of the algorithms or code that I provided.
– Greg Hurst Oct 12 '23 at 00:38SeedRandom[1]; reg = RandomPolyhedron[{"ConvexHull", 20}];convex hull area:Area[ConvexHullMesh[reg[[1, All, 1 ;; 2]]]] (* 0.477824 *)projection area:0.5Area[MeshRegion[reg[[1, All, 1 ;; 2]], Polygon[reg[[2]]]]] (* 0.477824 *)