INTERFACE Vertex; (* A vertex from a model *) IMPORT LR3, LR3x3; TYPE T = RECORD c: LR3.T; (* Cartesian coordinates *) fixed: BOOLEAN := FALSE; (* For simulator: TRUE if vertex is fixed. *) name: Name; END; TYPE List = ARRAY OF T; Num = CARDINAL; (* Index in a "List" *) Name = TEXT; CONST None = LAST(CARDINAL); (* NIL value for "Num" *) PROCEDURE Find(READONLY vertex: List; name: Name): Num; (* Returns the vertex number given the vertex name. *) PROCEDURE Copy(READONLY vertex: List; extra: CARDINAL := 0): REF List; (* Makes a copy of "vertex", with extra room at the end for "extra" new vertices. *) PROCEDURE GetNames(READONLY vertex: List; READONLY num: ARRAY OF Num): REF ARRAY OF Name; (* Makes a list of "vertex[num[i]].name" for all "i" *) PROCEDURE GetNums( READONLY vertex: List; prefix: TEXT; READONLY name: ARRAY OF Name; ): REF ARRAY OF Num; (* Makes a list of "Find(vertex, name[i])" for all "i". If the "prefix" is not empty, prepends the "prefix" and a period to each "name[i]". *) PROCEDURE BoundingBox(READONLY vertex: List): ARRAY [0..1] OF LR3.T; (* Bouning box of all vertices: "[0]" is min, "[1]" is MAX. *) PROCEDURE Center(READONLY vertex: List; READONLY num: ARRAY OF Num): LR3.T; (* The barycenter of the vertices "vertex[num[k]]", for all "k". *) PROCEDURE RingCurl(READONLY vertex: List; READONLY num: ARRAY OF Num): LR3.T; (* Pseudo-normal of the polygon "vertex[num[k]]". Given the vertices of a (possibly skew) polygon, returns a vector whose direction is normal to the (average) plane of the polygon, and whose length is twice the polygon's area. For a triangle, the result is merely the cross product of two consecutive sides. For a general polygon, it is the sum of such cross products, for any decomposition of the polygon into triangles that preserves the cyclic vertex order. Returns zero for two vertices, and fails for less than two. *) (* SPACE DEFORMATIONS *) (* The following procedures apply certain space transformations to the coordinates of the given vertices Note that applying these transformations to the corners of a cell may cause it to collapse or be turned ``inside-out.'' In the latter case, the orientation of its faces will be reversed. *) PROCEDURE Map(VAR vertex: List; READONLY R: LR3x3.T; READONLY t: LR3.T); (* Maps the coordinates "c" of every vertex of "vertex" by the afine transformation "c -> c R + t" where "R" is a linear map, and "t" is a translation vector. Note that "c" is viewed as a ROW vector. *) PROCEDURE Scale(VAR vertex: List; sx, sy, sz: LONGREAL); (* A special case of "Map": independent scaling along each axis. *) PROCEDURE Translate(VAR vertex: List; READONLY t: LR3.T); (* A special case of "Map": translation by "t". *) PROCEDURE Bend(VAR vertex: List; radius: LONGREAL); (* Bends the vertices around an axis that is parallel to the "Y" axis, and cuts the "X" axis at "X = +radius". The bending preserves the "Y" coordinate, and turns vertical lines into circles parallel to the "XZ" plane, whose centers lie on the bending axis. A plane that was originally horizontal at a given "Z" coordinate will be mapped to a plane through the bending axis that is titled by "Z/radius" (counterclockwise as seen from positive Y). Thus, the plane "X=0" becomes rolled up into a cylinder, without distortion; other planes paralell to it are stretched or compressed vertically, and then rolled up into concentric cylinders. *) PROCEDURE Twist(VAR vertex: List; rate: LONGREAL); (* Twists the object around the "Z" axis, by the given rate. The twisting rotates each point around the "Z" axis by an agle equals to "rate" times the point's "Z" coordinate. *) PROCEDURE Taper(VAR vertex: List; zLim: LONGREAL); (* Deforms the model by shrinking the top and expanding the bottom (or vice-versa). More precisely, keeps the "Z" coordinate unchanged, and scales "X" and "Y" by the factor "1 - Z/zLim". Note that the plane "Z=0" is unchanged, whereas the plane "Z=zLim" shrinks to a point. If "zLim" is negative, the object will be expanded at the top and compressed at the bottom. Note also that this is NOT a projective transformation, hence it does NOT preserve coplanarity, orientation, etc. *) PROCEDURE Bloat(VAR vertex: List; height, factor: LONGREAL); (* Deforms the model by gradually expanding the parts with "ABS(Z) < height" by up to "1+factor". The parts with "ABS(Z)" slightly greater than "height" are gradually shrunk by the inverse factor. More precisely, the "Z" coordinate is unchanged, whereas the "X" and "Y coordinates are scaled by alpha = exp(factor * (1 - r^2)/(1 + r^2)^2) where "r = Z/height". Note that the scale "alpha" is equal to "exp(factor)" when "Z=0", and tends to 1 when "ABS(Z)=height" or "ABS(Z) -> oo". *) PROCEDURE Sag(VAR vertex: List; height, factor: LONGREAL); (* Deforms the model by gradually displacing the parts with "ABS(Z) < height" by "factor*height" in the "+X" direction. The parts with "ABS(Z)" slightly greater than "height" are gradually shifted in the opposite direction. More precisely, the "Z" coordinate is unchanged, whereas the "X" coordinate is incremented by delta = factor * height * (1 - r^2)/(1 + r^2)^2 where "r = Z/height". Note that the displacement "delta" is equal to "factor*height" when "Z=0", and tends to 0 when "ABS(Z)=height" or "ABS(Z) -> oo". *) PROCEDURE Wiggle(VAR vertex: List; height, slope: LONGREAL); (* Deforms the model by gradually shearing the parts with "ABS(Z) < height" in the "+X" direction by the given "slope" (defined as "dX/dZ"). The parts with "ABS(Z)" slightly greater than "height" are gradually sheared with the opposite slope. More precisely, the "Z" coordinate is unchanged, whereas the "X" coordinate is incremented by delta = slope * Z * (1 - r^2)/(1 + r^2)^2 where "r = Z/height". Note that the displacement "delta" is equal to 0 when "Z=0" or "ABS(Z)=height" or "ABS(Z) -> oo". *) (* USEFUL HACKS *) PROCEDURE Det(READONLY p, q, r, s: LR3.T): LONGREAL; (* Determinant of the four points "(p,q,r,s)". The result is six times the volume of the tetrahedron, with plus sign iff the poligonal path formed by those vertices, in sequence, is a right-handed screw. *) END Vertex.