Povray code-trunc.inc

```
/\* This program is free software: you can redistribute it and/or modify it
 \* under the terms of the GNU General Public License as published by the Free
 \* Software Foundation, either version 3 of the License, or (at your option)
 \* any later version.
 \*
 \* This program is distributed in the hope that it will be useful, but WITHOUT
 \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 \* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 \* more details.
 \*
 \* You should have received a copy of the GNU General Public License along with
 \* this program. If not, see <http://www.gnu.org/licenses/>
 \*/

/\* Truncate polyhedron \*/

/\* This module will truncate a polyhedron description. On entry to this
 \* module:
 \* NumPolyVertices: The number of vertices prior to truncation
 \* PolyVertices: List of vertices to truncate
 \* NumPolyEdges: The number of edges of the base polyhedron
 \* PolyEdges: List of edges
 \* NumPolyFaces: The number of faces of the base polyhedron
 \* PolyFaces: List of faces
 \* PolyFaceDensity: Density of the faces, default 1
 \* PolyTruncPoint: Point to truncate the edges. If omitted, it is
 \* calculated
 \* PolyFaceTexture: Index of the texture of the original faces. Defaults
 \* to 0
 \* PolyVertexTexture: Index of the texture of the generated faces.
 \* defaults to 1
 \* ReserveVertices: Number of extra points to reserve for false vertices.
 \* defaults to 0
 \* ReserveFaces: Number of extra face segments to reserve for
 \* non-convex faces. defaults to 0
 \*
 \* On exit:
 \* NumVertices: The number of vertices in the truncated polyhedron
 \* Vertices: List of vertices
 \* Circumradius: The circumradius of the resultant polyhedron
 \* NumEdges: The numver of edges in the truncated polyhedron
 \* Edges: List of edges
 \* NumFullFaces: The number of faces in the truncated polyhedron
 \* FullFaces: List of faces
 \* FullFaceSizes: Number of edges in each vertex
 \* NumFaces: Number of faces after splitting
 \* Faces: List of faces split into triangles
 \* FaceTextureIndex: List of texture indices
 \*/

#ifndef (PolyFaceDensity)
 #declare PolyFaceDensity = 1;
#end

#local FaceValency = 2 \* NumPolyEdges / NumPolyFaces;
#local VertexValency = 2 \* NumPolyEdges / NumPolyVertices;

#ifndef (PolyTruncPoint)
 #local T = tan(PolyFaceDensity \* pi / (2 \* FaceValency));
 #declare PolyTruncPoint = (1 - T \* T) / 2;
#end

#ifndef (PolyFaceTexture)
 #declare PolyFaceTexture = 0;
#end

#ifndef (PolyVertexTexture)
 #declare PolyVertexTexture = 1;
#end

#ifndef (ReserveVertices)
 #declare ReserveVertices = 0;
#end

#ifndef (ReserveFaces)
 #declare ReserveFaces = 0;
#end
// Generate the vertices
#local Scale = 1 / (2 \* PolyTruncPoint);
#declare NumVertices = 2 \* NumPolyEdges;
#declare Vertices = array[NumVertices + ReserveVertices];

#for (V, 0, NumPolyEdges - 1, 1)
 #declare Vertices[2 \* V ] = ((1 + PolyTruncPoint) \*
 PolyVertices[PolyEdges[V][0]] +
 (1 - PolyTruncPoint) \*
 PolyVertices[PolyEdges[V][1]]) \* Scale;
 #declare Vertices[2 \* V + 1] = ((1 - PolyTruncPoint) \*
 PolyVertices[PolyEdges[V][0]] +
 (1 + PolyTruncPoint) \*
 PolyVertices[PolyEdges[V][1]]) \* Scale;
#end

// Generate the edges
#declare NumEdges = NumPolyEdges + NumVertices;
#declare Edges = array[NumEdges][2];

#for (E, 0, NumPolyEdges - 1, 1)
 #declare Edges[E][0] = 2 \* E;
 #declare Edges[E][1] = 2 \* E + 1;
#end

// VFaceEdges contains a list of the edges surrounding each vertex
#local VFaceEdges = array[NumPolyVertices][VertexValency];
#local NextVFaceEdge = array[NumPolyVertices];
#for (V, 0, NumPolyVertices - 1, 1)
 #declare NextVFaceEdge[V] = 0;
#end

#for (F, 0, NumPolyFaces - 1, 1)
 #for (FV, 0, FaceValency - 1, 1)
 #local ThisEdge = NumPolyEdges + F \* FaceValency + FV;
 #local Last = PolyFaces[F][mod(FV + FaceValency - 1, FaceValency)];
 #local This = PolyFaces[F][FV];
 #local Next = PolyFaces[F][mod(FV + 1, FaceValency)];
 #local Vertex1 = -1; // If either of the two edges are not found, the
 #local Vertex2 = -1; // relevant Vertex# will be -1, generating an error
 #for (E, 0, NumPolyEdges - 1, 1)
 #if ((PolyEdges[E][0] = Last) & (PolyEdges[E][1] = This))
 #declare Vertex1 = 2 \* E + 1;
 #elseif ((PolyEdges[E][0] = This) & (PolyEdges[E][1] = Last))
 #declare Vertex1 = 2 \* E;
 #end
 #if ((PolyEdges[E][0] = Next) & (PolyEdges[E][1] = This))
 #declare Vertex2 = 2 \* E + 1;
 #elseif ((PolyEdges[E][0] = This) & (PolyEdges[E][1] = Next))
 #declare Vertex2 = 2 \* E;
 #end
 #end
 #declare Edges[ThisEdge][0] = Vertex1;
 #declare Edges[ThisEdge][1] = Vertex2;
 #declare VFaceEdges[This][NextVFaceEdge[This]] = ThisEdge;
 #declare NextVFaceEdge[This] = NextVFaceEdge[This] + 1;
 #end
#end
#declare Circumradius = vlength(Vertices[0]);

// Generate the faces
#declare NumFullFaces = NumPolyFaces + NumPolyVertices;
#local FaceArrayWidth = max(VertexValency, 2 \* FaceValency);
#declare FullFaces = array[NumFullFaces][FaceArrayWidth];
#declare FullFaceSizes = array[NumFullFaces];

#for (F, 0, NumPolyFaces - 1, 1)
 #declare FullFaceSizes[F] = 2 \* FaceValency;
 #for (FE, 0, FaceValency - 1, 1)
 #local From = PolyFaces[F][FE];
 #local To = PolyFaces[F][mod(FE + 1, FaceValency)];
 #for (E, 0, NumPolyEdges - 1, 1)
 #if ((From = PolyEdges[E][0]) & (To = PolyEdges[E][1]))
 #declare FullFaces[F][2 \* FE ] = 2 \* E;
 #declare FullFaces[F][2 \* FE + 1] = 2 \* E + 1;
 #elseif ((From = PolyEdges[E][1]) & (To = PolyEdges[E][0]))
 #declare FullFaces[F][2 \* FE ] = 2 \* E + 1;
 #declare FullFaces[F][2 \* FE + 1] = 2 \* E;
 #end
 #end
 #end
#end

#for (V, 0, NumPolyVertices - 1, 1)
 #local ThisEdge = VFaceEdges[V][0];
 #local ThisVert = Edges[ThisEdge][1];
 #local NextEdge = 0;
 #declare FullFaces[NumPolyFaces + V][0] = ThisVert;
 #for (E, 1, VertexValency - 1, 1)
 #local Found = false;
 #for (E1, 1, VertexValency - 1, 1)
 #if (!Found)
 #local VFE = VFaceEdges[V][E1];
 #if (VFE != ThisEdge)
 #if (Edges[VFE][0] = ThisVert)
 #declare Found = true;
 #declare ThisVert = Edges[VFE][1];
 #declare ThisEdge = VFE;
 #elseif (Edges[VFE][1] = ThisVert)
 #declare Found = true;
 #declare ThisVert = Edges[VFE][0];
 #declare ThisEdge = VFE;
 #end
 #end
 #end
 #end
 #if (!Found)
 #error "Cannot find edge"
 #end
 #declare FullFaces[NumPolyFaces + V][E] = ThisVert;
 #end
 #declare FullFaceSizes[NumPolyFaces + V] = VertexValency;
#end

// Finally, to triangulate the faces
#declare FaceValency = 2 \* FaceValency;
#local NumFaceFaces = (FaceValency - 2) \* NumPolyFaces;
#local NumVertexFaces = (VertexValency - 2) \* NumPolyVertices;

#declare NumFaces = NumFaceFaces + NumVertexFaces;
#declare Faces = array[NumFaces + ReserveFaces][3];
#declare FaceTextureIndex = array[NumFaces + ReserveFaces];
#debug concat("FaceValency = ", str(FaceValency, 1, 0), "\n")
#debug concat("VertexValency = ", str(VertexValency, 1, 0), "\n")

#for (F, 0, NumPolyFaces - 1, 1)
 #local Offset = (FaceValency - 2) \* F - 1;
 #for (V, 1, FaceValency - 2, 1)
 #declare Faces[Offset + V][0] = FullFaces[F][0];
 #declare Faces[Offset + V][1] = FullFaces[F][V];
 #declare Faces[Offset + V][2] = FullFaces[F][V + 1];
 #declare FaceTextureIndex[Offset + V] = PolyFaceTexture;
 #end
#end

#for (F, 0, NumPolyVertices - 1, 1)
 #local Offset = NumFaceFaces + (VertexValency - 2) \* F - 1;
 #for (V, 1, VertexValency - 2, 1)
 #declare Faces[Offset + V][0] = FullFaces[F + NumPolyFaces][0];
 #declare Faces[Offset + V][1] = FullFaces[F + NumPolyFaces][V];
 #declare Faces[Offset + V][2] = FullFaces[F + NumPolyFaces][V + 1];
 #declare FaceTextureIndex[Offset + V] = PolyVertexTexture;
 #end
#end

```