home *** CD-ROM | disk | FTP | other *** search
- //
- // pyramid.inc version 1.0
- // Create multi-sided pyramid objects using a variety of parameters.
- //
- // Donated to the public domain
- //
- // Written by Michael D Johnson
- // mdjohnson@voyager.net or redbeard@quark.gmi.edu
- // http://quark.gmi.edu/~redbeard
- //
- // Most recent version is available at
- // http://quark.gmi.edu/~redbeard/raytrace/POVRay-Util.html
- //
- //
- // Variables
- // ---------
- // Only one of each set of indented variables need be set, as determined
- // by the variable immediately preceeding each set. Values in brackets []
- // are default values. Note that once the routine is called, there can be
- // no defaults assumed, although the values from the last call are still in
- // effect, since defaults are assigned only to undefined variables.
- //
- // Sides [4] Number of sides
- // HeightMode [0] Method for determining height of pyramid.
- // 0 - Height, 1 - SideAngle, 2 - SideHeight, 3 - Edge.
- // All values are calculated.
- // Height [0.5] Height to make pyramid
- // SideAngle [55] Angle from base plane of the sides.
- // SideHeight [1] The "height" of a side of the pyramid. Actually, the
- // distance from the center of a base edge to the apex
- // of the pyramid
- // Edge [1] Length of an edge other than a base.
- // BaseMode [0] Method of choosing length of base. 0 - Use Base
- // 1 - Use Radius, 2 - use IRadius/ File calculates all.
- // Base [1] Length of one side of the base
- // Radius [1] Radius of circumscibed circle
- // IRadius [1] Radius of an inscribed circle
- //
- // DEBUG [na] If DEBUG is declared to a true value, then some
- // debugging output is created. If DEBUG is
- // undefined or false, then this output is bypassed.
- //
- // Return Values
- // -------------
- // These variables are set in addition to the above variables.
- //
- // IAngle Angle between two edges of the base
- // CAngle Angle formed at center between two adjacent base
- // verticies. In other words, the angle that
- // the pyramid can be rotated (about y axis) and
- // maintain apparent orientation. There is probably
- // a simpler way to say this, but I cant think of it.
- //
- // Pyramid is centered at origin, with base on y=0 plane. Height is measured
- // in positive y direction. One edge lies parallel to the x axis in the
- // positive z direction.
- //
- // Use:
- // ----
- // 1 Set appropriate variables
- // 2 Use a line similar to:
- // object { #include "pyramid.inc" }
- //
- // Side note:
- // ----------
- // The bounding box used within the intersection reduces trace time by
- // roughly 75%. Always use bounding_boxes of you can for intersections and
- // differences.
- //
-
- #ifndef (Sides) #declare Sides = 4 #end
- #ifndef (HeightMode) #declare HeightMode = 0 #end
- #ifndef (Height) #declare Height = 0.5 #end
- #ifndef (SideAngle) #declare SideAngle = 55 #end
- #ifndef (SideHeight) #declare SideHeight = 1 #end
- #ifndef (Edge) #declare Edge = 1 #end
- #ifndef (BaseMode) #declare BaseMode = 0 #end
- #ifndef (Base) #declare Base = 1 #end
- #ifndef (Radius) #declare Radius = 1 #end
-
- #if (Sides < 3) #error "Must have at least 3 Sides." #end
- #declare CAngle = 360 / Sides // Degrees of rotation between sides
- #declare _pyramid_cr = radians(CAngle)
- #declare IAngle = 180 - CAngle // Internal angles of base
- #declare _pyramid_ir = radians(IAngle)
-
- // The _pyramid_*s below are to permit the entry of each equation used only
- // once, simplifying debugging.
- #switch (int(BaseMode))
- #case (0) // Know the length of an edge of the base.
- #declare _pyramid_r = false
- #declare _pyramid_i = false
- #break
- #case (1) // Know the radius of a circumscribed circle
- #declare Base = 2 * Radius * sin(_pyramid_cr / 2)
- #declare _pyramid_r = true
- #declare _pyramid_i = false
- #break
- #case (2) // Know the radius of an inscribed circle
- #declare Base = IRadius * 2 / tan(_pyramid_ir / 2)
- #declare _pyramid_r = false
- #declare _pyramid_i = true
- #break
- #else
- #error "Invalid value for BaseMode."
- #end
-
- // If a value is not known, calculate it.
- #if (!_pyramid_r) #declare Radius = Base / (2 * sin(_pyramid_cr / 2)) #end
- #if (!_pyramid_i) #declare IRadius = Base * tan(_pyramid_ir / 2) / 2 #end
-
- // Same thing as for the base.
- #switch (int(HeightMode))
- #case (0) // Know the height
- #declare SideAngle = degrees(atan2(Height, IRadius))
- #declare _pyramid_s = false
- #declare _pyramid_d = false
- #declare _pyramid_h = true
- #declare _pyramid_a = true
- #break
- #case (1) // Know the angle from the base to a side
- #declare _pyramid_a = true
- #declare _pyramid_h = false
- #declare _pyramid_s = false
- #declare _pyramid_d = false
- #break
- #case (2) // Know the "height" of a side
- #declare _pyramid_a = false
- #declare _pyramid_h = false
- #declare _pyramid_s = true
- #declare _pyramid_d = false
- #break
- #case (3) // Know the length of an edge of a side
- #declare SideHeight = pow(Edge, 2) - pow(Base / 2, 2)
- #declare _pyramid_a = false
- #declare _pyramid_h = false
- #declare _pyramid_s = true
- #declare _pyramid_d = true
- #break
- #else
- #error "Invalid value for HeightMode."
- #end
-
- #if (_pyramid_s & (!_pyramid_a))
- #declare SideAngle = degrees(acos(IRadius / SideHeight))
- #declare _pyramid_a = true
- #end
-
- // This error is only generated if something has been improperly changed
- #if (!_pyramid_a) #error "Internal error." #end
-
- // Calculate the values if needed.
- #if (!_pyramid_h) #declare Height = IRadius * tan(radians(SideAngle)) #end
- #if (!_pyramid_s)
- #declare SideHeight = IRadius / cos(radians(SideAngle))
- #end
- #if (!_pyramid_d)
- #declare Edge = sqrt(pow(Base / 2, 2) + pow(SideHeight, 2))
- #end
-
- // Build the pyramid. It is the intersection of a base plane and planes
- // forming the sides. It is bounded by a cone (since that is the closet
- // thing to it that bounds it)
- intersection
- {
- plane { -y, 0 }
- #declare IRadiusoop = 0
- #while (IRadiusoop < Sides)
- plane
- {
- y, 0
- rotate x * SideAngle
- translate z * IRadius
- rotate y * IRadiusoop * CAngle
- }
- #declare IRadiusoop = IRadiusoop + 1
- #end
- bounded_by { cone { 0, Radius, y * Height, 0 } }
- }
-
- // Display the various calculated values on the debug stream.
- #ifdef (DEBUG)
- #if (DEBUG)
- #debug "Values from pyramid.inc:"
- #debug concat("\n Sides: ", str(Sides, 0, 0))
- #debug concat("\n HeightMode: ", str(HeightMode, 0, 0))
- #debug concat("\n Height: ", str(Height, 0,-1))
- #debug concat("\n SideAngle: ", str(SideAngle, 0,-1))
- #debug concat("\n SideHeight: ", str(SideHeight, 0,-1))
- #debug concat("\n Edge: ", str(Edge, 0,-1))
- #debug concat("\n BaseMode: ", str(BaseMode, 0, 0))
- #debug concat("\n Base: ", str(Base, 0,-1))
- #debug concat("\n Radius: ", str(Radius, 0,-1))
- #debug concat("\n CAngle: ", str(CAngle, 0,-1))
- #debug concat("\n IAngle: ", str(IAngle, 0,-1))
- #debug concat("\n IRadius: ", str(IRadius, 0,-1), "\n\n")
- #end
- #end
-
-