// #FILE timestamp.txt /* Last edited on 2025-03-13 05:16:58 by stolfi */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Octf.h #ifndef Octf_H #define Octf_H // #TIMESTAMP /* Last edited on 2007-01-30 19:47:50 by stolfi */ /* The Facet-Edge data structure for representing the topology of 3D maps. */ #define Octf_H_copyright \ "Copyright © 1998 Universidade Estadual de Campinas (UNICAMP)" #define Octf_H_author \ "The Modula-3 version of this interface was created in 1998" \ "by Luis Arturo Perez Lozada, UNICAMP, inspired on the " \ "Modula-3 implementation of the quad-edge data structure by " \ "J.Stolfi and R.M.Rosi (ca. 1994). " \ "It was converted to C and substantially revised in jan/2007 by J.Stolfi." #include #include #include #include #include /* [!!! RENAMES TO CONSIDER !!!] */ /* node -> site / knot / */ /* wall -> face */ /* edge -> link / line */ /* flag -> chip / flap / side / tile / face / trig */ /* link -> edge / bond */ /* chip -> bloc / quad */ /* knot -> site */ /* place -> spot */ /* wedge -> */ /* flow -> order */ /* curl -> whorl / clock */ /* hand -> twist / screw / helix */ /* BASIC CONCEPTS AND NOTATION A facet-edge data structure is meant to represent the topology of a map on some 3D topological space. The structure was described by D.Dobkin and J.Laszlo ("D&L" below) in the paper "Primitives for the Manipulation of Three-Dimensional Subdivisions" (/Algorithmica/, 1989). For the purpose of these comments, at any time there is a single facet-edge structure in the program's address space, representing a single map {M} over a single topological space {X}. All concepts of point-set topology used here (closure, boundary, connectedness, homeomorphic, etc.) are relative to the topology of {X}. The space {X} and the map {M} are defined by the structure up to an homeomorphism, and their topology changes implicitly as the structure gets modified. However, each connected component of the structure represents a distinct connected component of {M}, lying on a distinct connected component of {X}; and can be traversed, modified, and written out to disk without interfering with any other component. Thus, one may work with each connected component of {M} as if it were a separate instance of the data structure. The map {M} is a partition of {X} into /elements/. Each element {e} is homeomorphic to {R^k} for some {k} in {0..3}; we denote its dimension {k} by {e.dim}. We will call the element a /node/, /edge/, /wall/, or /cell of {M}/, depending on whether its dimension is 0,1,2, or 3. (In the original paper, those elements are called /vertices/, /edges/, /facets/ and /polyhedra/, respectively.) If {x} is any point of {X}, we write {x@M} for the unique element of {M} that owns {x}. The /{M}-type of a point {x}/ of {X} is the integer {x@M.dim}, the dimension of the unique element of {M} that owns {x}; which we denote by {(x,M).typ}. If {Y} is any subset of {X}, we write {Y$} for the topological closure of {Y} (in {X}). If {Y,Z} are two subsets of {X}, we say /{Y} incides on {Z}/, or equivalently that /{Z} bounds {Y}/, iff {Y$} intersects {Z}. */ /* BARYCENTRIC SUBDIVISION The facet-edge structure is defined in terms of an auxiliary map on {X}, a triangulation (`simplicial map') {S} that is a barycentric sudivision of {M}. To reduce confusion, the elements of {S} with dimensions 0,1,2,3 will be called /knots/, /links/, /flag/ and /chips/, respectively. Each element {e} of {M} contains a unique knot {e!} of {S}, the /centroid of {e}/. Conversely, each element {r} of {S} is contained in a unique element {e} of {M}, which we will denote by {r@M}. The /{M}-type of an element {r} of {S}/ is the set of integers {{ (x,M).typ : x in r$ }}. It coincides with the set {{ v@M.dim }} where {v} ranges over the knots of {S} that bound {r}. Note that a {k}-dimensional element of {S} has {k+1} distinct bounding knots, all with distinct types. We write {(r,M).knt[i]} for the bounding knot of {r} with {M}-type {i}, when it exists. It follows that each chip {s} of {S} defines a fairly precise location in a map {M}. In particular, it defines a quadruple of elements {(e[0],..e[3])} such that each {e[i]} has dimension {i} and is incident on {e[j]} for all {j0}, admits exctly two distinct consistent /internal orientations/ that specify the sense for local motions of motion WITHIN {Y} at any point of {Y}. In particular, if {Y} is a line ({k==1}), the internal orientation is a /flow/, a specific direction of travel ALONG {Y}. If {Y} is a surface ({k==2}) the orientation is a /curl/, a specific sense of turning WITHIN {Y}. If {Y} is a solid ({k==3}), the orientation is a /twist/, a specific handedness for local helical motions INSIDE {Y}. On the other hand, if {Y} is a single point ({k==0}), it has only one internal orientation. If the subset {Y} is a {k}-ball with {k<3}, and has a neighborhood in {X} that is a 3-ball, then {Y} also admits two distinct /external orientations/, which are independent of the internal ones. If {Y} is a surface, line, or isolated point, the external orientation is, respectively, a direction of motion ACROSS {Y} (a /flux/), a sense of turning AROUND {Y} (a /spin/), and a specific handedness for helical motion ABOUT {Y} (a /twist/). */ /* ORIENTATIONS OF BARYCENTRIC ELEMENTS The barycentric subdivision {S} defines a specific internal orientation for every chip {s} of {S}, and also for links of {S} with {M}-types {{0,1}} and {{2,3}} (the /edge links/), and flag of {S} with {M}-types {{0,1,2}} and {{1,2,3}} (the /wall flag/). Specifically, the /intrinsic flow/ on a link with {M}-type {{0,1}} is, by definition, the one that goes from the knot with {M}-type 0 to the knot with {M}-type 1. Dually, the intrinsic flow on a link with {M}-type {{2,3}} goes from the knot with {M}-type 3 to that of {M}-type 2. The /intrinsic curl/ on a flag with {M}-type {{0,1,2}} is, by definition, the one that traverses the flag's perimeter going through knots 0,1,2, in that order; while the intrinsic curl on a {{1,2,3}} flag goes through its bounding knots in the order 3,2,1. Also, the /intrinsic twist/ at any point inside any chip {s} is the one that agrees with the intrinsic flows on its {{0,1}} and {{2,3}} bounding links. Informally, the twist that moves with the flow on the {{0,1}} link while turning in the sense of the flow on the {{2,3}} link. Note that these definitions specify the same INTERNAL orientations on chips, edge links, and wall flag, no matter which of the two maps we use to assign types. Also, the internal orientations of those links and flag are defined without reference to a specific chip. Since the closure of any chip {s} is simply-immersed in {X} (i.e. is homeomorphic to a closed 3-ball), the intrinsic twist of {s} can be consistently extended to its closure {s$}. Note however that any two chips that share a flag will define OPPOSITE twists at any point on that flag. A specific chip {s} also determines EXTERNAL orientations for the its wall flag, its edge links, and its node knots (those with {M}-type {{0}} or {{3}}). By definition, the spin around its {{0,1}} link is the one that agrees across {s} with the intrinsic flow on the opposite {{2,3}} link; and symmetrically for the spin around the {{2,3}} link. Also, the flux deermined by {s} across its {{0,1,2}} and {{1,2,3}} flag are, by definition, those that leave the chip {s}. Note that these EXTERNAL orientations for links and flag do NOT depend on which of the two maps we use as reference, but they DO depend on the chip {s}. In particular, two chips that share a {{0,1,2}} or {{1,2,3}} flag {t} will determine opposite fluxes across {t}, and opposite spins around the shared {{0,1}} or {{2,3}} link. */ /* ORIENTATIONS OF ELEMENTS The intrinsic flow along a {{0,1}} link {r} determines by extension a flow along the map edge {e = r@M} that contains {r}. The two {{0,1}} links on an edge {e} are always distinct, and determine opposite flows along {e}. In the same way, the intrinsic curl of a {{0,1,2}} flag can be extended to a curl for the wall it belongs to. The flag that belong to any given wall {f} can be partitioned into two subsets {A,B} of equal size, such that any flag in {A} determines a specific curl within the wall, and any flag in {B} determines the opposite curl. For cells, the situation is more complicated. suppose that all the chips contained in a cell {c} can be partitioned into two subsets {A,B}, such that any two adjacent chips are always in distinct subsets. In that case, the cell {c} admits two orientations, and chip {s} in {A} of {B} determines a specific twist for the whole cell {c}: namely, the one that agrees with intrinsic twist of {s}. Moreover, all chips in {A} determine the same twist for {c}, while all chips in {B} determine the opposite twist. In that case, we say that the cell {c} is /orientable/. On the other hand, if such a partition does not exist, then the cell's centroid {c!} must be a /non-manifold point of {X}/, one that does not have a ball-like neighborhood; indeed, it must be a /non-orientable point/, one that has no orientable neighborhood. In that case, one cannot define the concept of `twist' at {c}; and all its chips are equivalent in that regard. The same considerations apply to the cells of the dual map. So a chip {s) that incides on a node {v} of {M} defines a twist inside the cell {v*} of {M*}, and hence a twist about {v} --- provided that the chips that incide on {v} can be partitioned into two sets {A,B} with the property stated above. Otherwise, {v} is a non-orientable (and non-manifold) point of {X}, and one cannot define the concept of `twist' about that point. The facet-edge data structure is such that every point of the underlying manifold {X} has ball-like neighborhood, except possibly for the nodes of {M} and {M*} (i.e.,nodes and cell centroids of {M}). Note that a cell may be orientable even if its centroid does not have a ball-like neighborhood. Note also that a connected component of {X} may be non-orientable even if all its points have ball-like neighborhoods. */ /* PLACES A /place/ in the facet-edge structure is a pair {(s,M)} where {s} is a chip of {S} (denoted {p.s}) and {M} is one the two maps represented by the structure (denoted {p.M}). The concepts defined for chips of {S} are naturally extended to places; with the advantage that, if the concept is defined relative to a map, the map {p.M} is implicitly used. Thus, for instance, if {r} is an {S}-element that bounds the chip {p.s}, the /{p}-type of {r}/ is the set {(r,p.M).typ}. The /knot of {p} with type {i}/ is knot {p.knt[i] = (p.s,p.M).knt[i]}. And so on. */ typedef struct PlaceRec_t *Place_t; /* A {Place_t} value represents a place in the facet-edge structure. */ vec_typedef(Place_vec_t,Place_vec,Place_t); /* A vector of {Place_t}s. */ /* DUAL PLACES The /dual of a place {p}/ is {p* = (p.s,p.M*)}, the place defined by the same chip on the dual map. Obviously, {p** = p} for any place {p}. */ Place_t Dual(Place_t p); /* Returns the dual {p*} of the place {p}. */ /* THE ELEMENTS OF A PLACE If {p} is a place, we define /the elements of {p}/ as the quadruple {p.elm} such that {p.elm[i] = (p.s,p.M).elm[i]} for {i} in {0..3}. We will call {p.elt[0] = p.node} /the node of {p}/, {p.elt[1] = p.edge} /the edge of {p}/, {p.elt[2] = p.wall} /the wall of {p}/, and {p.elt[3] = p.cell} /the cell of {p}/, respectively. The elements of {p} are implicitly oriented as determined by the chip {p.s}. Note that two distinct chips {s,t} of {S} may define the same element sequences {(s,M).elm == (t,M).elm}. For instance, if an edge {e} of {M} is a loop, then there are two chips in {S} (and, therefore, two places in {M}) which have the same elements. However, those two places can be distinguished by the orientations they define on those elements. Conversely, as pointed out by D&L, there is a one-to-one correspondence between the places on {M} and all pairs {(a,b)} where {a} is an internally oriented edge of {M} (an edge with a specific flow) and {b} is an internally oriented edge of {M*}, such that {a*} is incident on {b} and vice versa. In one direction, the correspondence is {(a,b) = (p.edge,p*edge)}, which we will denote by {p.pair}. In the other direction, observe that the orientation of {a} determines a unique link {r} of {M}-type {{0,1}}, namely the one at the origin end of {a}; and {b} determines a unique {{2,3}} link {t}. These two links uniquely determine the chip {p.s}, and the order of the pair {(a,b)} determines the map {p.M}. */ /* DUALITY AND ORIENTATION Note that {p*} and {p} define the same orientation on the chip {p.s==p*.s}. Indeed, the internal orientation of any element {e = p.elt[i]} as implied by {p}, agrees with the external orientation of {e* = p*.elt[3-i]}, as implied by {p*}, at their intersection point {e! == e*!}. Thus, for example, the flow along the edge {e = p.edge} of {M} agrees with the flux across the wall {e* = p*.wall} of {M*}, at the point where {e} crosses {e*}. Similarly, the curl inside the wall {f = p.wall} of {M} agrees with the spin around the edge {f* = p*.edge} of {M*}, at the point where {f*} crosses {f}. */ /* PLACE-FLIPPING OPERATIONS For each chip {s} of the barycentric subdivision {S}, and each {i} in {0..3}, there is a unique chip {t} that is distinct from {s} but shares with it a flag with {M}-type {0..3}\{i}. We call {t} the /{i}-flip of {s} relative to {M}/, denoted {(s,M).flp[i]}. The {flp} operations extend naturally to places; namely, if {p} is a place, then {p.flp[i]} is the place {((p.s,p.M).flp[i], p.M)}. Note that {p.flp[i].flp[i] == p} (i.e., {flp[i]} is its own inverse), and {p*.flp[i] == p.flp[3-i]*}, for any place {p} and type {i}. The efect of {flp[i]} on the element tuple of {p} is to exchange the {i}-dimensional element by its `natural partner', while preserving the other elements with opposite internal orientations. Se below for explanations about the `natural partner'. The {flp[i]} operators completely determine the topology of {S} and {M}, up to an homeomorphism; and vice-versa. They allow walking from place to place all over either map. For example, one can enumerate the cells of {M} that surround a given edge {e} of {M} by starting from any place {p} on {M} such that {p.s} is incident to {e}, and using {flp[2]} and {flp[3]} operations --- which vary {p.wall} and {p.cell}, respectively, while preserving {p.edge} and its endpoint {p.node}. Similary, one can visit all places with the same node {v} by stating from any such place and using {flp[1]}, {flp[2]} and {flp[3]} in all combinations. */ Place_t Flip(Place_t p, uint i); /* Given a place {p}, returns the place {p.flp[i]}. The facet-edge structure is implemented in such a way that this operation takes constant time, independent on the map's topology. */ Place_t Flip0(Place_t p); /* The same as {Flip(p,0)}. It replaces {p.node} by the node at the other endpoint of {p.edge}, while preserving {p.edge}, {p.wall}, and {p.cell}, with reversed internal orientations. */ Place_t Flip1(Place_t p); /* The same as {Flip(p,1)}. It replaces {p.edge} by another edge on the boundary of {p.wall} that is also incident to {p.node}, with flow directed away from {p.node}, while preserving {p.node}, {p.wall}, and {p.cell} --- the last two with reversed internal orientations. */ Place_t Flip2(Place_t p); /* The same as {Flip(p,2)}. It replaces {p.wall} by another wall on the boundary of {p.cell} that is also incident to {p.edge}, with curl that agrees with the flow of {p.edge}, while preserving {p.node}, {p.edge}, and {p.wall} --- the last two with reversed internal orientations. */ Place_t Flip3(Place_t p); /* The same as {Flip(p,3)}. It replaces {p.cell} by the cell on the other flag of {p}'s wall, while preserving {p.node}, {p.edge}, and {p.wall} --- the last two with reversed internal orientations. */ Place_t Spin(Place_t p); /* D&L's original name for {Flip3}. */ /* PLACE ORIENTATION A place {p} defines a unique chip {p.s} of {S}; therefore, as discussed above, it determines internal and external orientations for its elements, whenever they can be defined. In particular, {p} usually determines a a twist around the vertex {v=p.node}; a flow along the edge {e=p.edge}, and a spin around it; a curl on the wall {f=p.wall}, and a flux cross it; and a twist inside the cell {c=p.cell}. However, the twists around {v} and inside {c} are defined only if the {v} and {c!}, respectively, have orientable neighborhoods. As noted above, the places {p} and {p.flp[i]}, for anly {p} and {i}, define opposite twists on any point of their shared flag. We say that two places {p,q} on the same map are /evenly connected/ (resp. /oddly connected/) iff one can be obtained from the other by an even (resp. odd) number of {flp} operations. Note that {p.s} and {q.s} lie on the same connectred component of the space {X} iff they are either evenly connected or oddly connected. It turns out that a connected component {Y} of the space {X} is orientable only if there is no place on the corresponding component {N} of {M} that is oddly connected to itself. In that case, the set of places on the component {N} can be divided into two subsets {A,B}, such that {p} and {p.flp[i]} are on different subsets, for any {p} and {i}; and each subset defines a different consistent twist for the whole subspace {|N|}. Usually, the places {p} and {p.flp[i]} will determine opposite INTERNAL orientations for every element {p.elt[j]} with {j!=i}. Thus, for example, doing {p = p.flp[0]} may or may not change the node {p.node}, but always reverses the implied flow on the edge {p.edge}, the implied curl on the wall {p.wall}, and the implied twist on the cell {p.cell} (provided that the cell is orientable). The EXTERNAL orientations of {p}'s elements, on the other hand, are affected only in some cases. The twist around {p.node} is reversed by {flp[1],flp[2],flp[3]}; the spin around {p.edge} is preserved by {flp[0]} but reversed by {flp[2],flp[3]}; and the flux across {p.wall} is preserved by {flp[0],flp[1]} but reversed by {flp[3]}. */ /* NEARBY ELEMENTS The flow on {p.edge} determined by {p} always moves away from {p.node}; so {p.node} will also be called the /origin (node)/ of {p}, {p.orig}, while the node at the other endpoint of {p.edge}, which is {p.flp[0].node}, will be called {p}'s /destination (node)/, writen {p.dest}. Dually, the flux across {p.wall} is directed outwards from {p.cell}; so {p.cell} will be called the /hither (cell)/ of {p}, denoted {p.hith}, while the cell on the other flag of {p.wall}, namely {p.flp[3].cell}, is {p}'s /yonder (cell)/, written {p.yond}. We will also define {p}'s /back wall/, {p.back}, as {p.flp[2].wall}; and {p}'s /fork edge/, {p.fork}, as {p.flp[1].edge}. By definition, the internal and external orientations of the elements {p.dest}, {p.yond}, {p.back} and {p.fork} are defined by these formulas. */ /* DERIVED WALKING OPERATIONS By combining two or more {flp} operations, one obtains a variety of `walking operators' that move from place to place in a regular way. Walking operators that combine two (or an even number of) {flp} steps are interesting because they will transport the local twist of the manifold from the given place to the result place, coherently, across the flag traversed by those {flp}s. Thus, if the manifold {X} is orientable, they will preserve the twist of {X} that was defined by the argument {p}. */ Place_t FlipIJ(Place_t p, uint i, uint j); /* Returns {Flip(Flip(p,i), j) == p.flp[i].flp[j]}. */ Place_t Clock(Place_t p); Place_t Flip03(Place_t p); Place_t Flip30(Place_t p); /* "Doube orientation flip". In D&L terms, reverses both members of the edge pair {p.pair}. Exchanges {p.orig} with {p.dest}, but with reversed twists. Exchanges {p.hith} with {p.yond}, but with reversed twists. Preserves {p.edge}, but with reversed flow and spin. Preserves {p.wall}, but with reversed flux and curl. Equivalent to {Flip0(Flip3(p)) = p.flp[0].flp[3]}, and also to {Flip3(Flip0(p)) = p.flp[3].flp[0]}. Note that {Clock(Clock(p)) = p}. */ Place_t NextF(Place_t p); Place_t Flip32(Place_t p); /* "Next wall". In D&L terms, rotates {p.pair} one step arount {p.edge}, in its spin sense. Replaces {p.wall} by the next wall around {p.edge}, in {p.edge}'s spin sense. Replaces {p.cell} by the next cell in that sense, namely {p.yond}. Preserves {p.edge} and {p.node}. Equivalent to {Flip2(Flip3(p)) = p.flp[3].flp[2]}. */ Place_t PrevF(Place_t p); Place_t Flip23(Place_t p); /* "Previous wall". Inverse of {NextF}. Equivalent to {Flip3(Flip2(p)) = p.flp[2].flp[3]}. */ Place_t NextE(Place_t p); Place_t Flip01(Place_t p); /* "Next edge". In D&L terms, rotates {p.pair} one step arount {p.wall}, in its flow sense. Replaces {p.edge} by the next edge around {p.wall}, in {p.wall}'s curl sense. Replaces {p.node} by the next vertex in that sense, namely {p.dest}. Preserves {p.wall} and {p.cell}, including orientations. Equivalent to {Flip1(Flip0(p)) = p.flp[0].flp[1]}. */ Place_t PrevE(Place_t p); Place_t Flip10(Place_t p); /* "Previous edge". Inverse of {NextE}. Equivalent to {Flip0(Flip1(p)) = p.flp[1].flp[0]}. */ Place_t SymNF(Place_t p); Place_t Flip02(Place_t p); Place_t Flip20(Place_t p); /* "Symmetric node and face". In D&L terms, rotates {p.pair} by half a turn around the link that connects {p*.orig} and the centroid of {p.edge}. Reverses the flow and spin of {p.edge}. Replaces {p.node} by the opposite node, {p.dest}, with reversed twist. Replaces {p.wall} by the opposite wall, {p.back}, with reversed curl. Preserves {p.cell} and its twist. Equivalent to {Flip0(Flip2(p)) = p.flp[2].flp[0]} and also to {Flip2(Flip0(p)) = p.flp[0].flp[2]}. Note that {SymNF(SymNF(p)) = p}. */ Place_t SymEC(Place_t p); Place_t Flip31(Place_t p); Place_t Flip13(Place_t p); /* "Symmetric edge and cell". In D&L terms, rotates {p.pair} by half a turn around the link that connects {p.orig} with the centroid of {p*.edge}. Reverses the curl and flux of {p.wall}. Replaces {p.cell} by the opposite cell, {p.yond}, with reversed twist. Replaces {p.edge} by the opposite edge, {p.fork}, with reversed spin. Preserves {p.node} and its twist. Equivalent to {Flip3(Flip1(p)) = p.flp[1].flp[3]} and also to {Flip1(Flip3(p)) = p.flp[3].flp[1]}. Note that {SymEC(SymEC(p)) = p}. */ Place_t ONext(Place_t s); Place_t Flip21(Place_t p); /* "Next edge around the origin". In D&L terms, rotates {p.pair} around the link that connects {p.orig} to {p*.orig}, in the sense of the midpoint of {p*.edge} to the midpoint of {p.edge}, until the next wall-edge pair. In terms of the quad-edge structure, replace {p.edge} by the next edge on the boundary of {p.cell} that flows out of {p.orig}, turning around {p.orig} in the positive sense as seen from inside {p.cell}. Preserves {p.node} and {p.cell}, with their twists. Replaces {p.wall} by the opposite face {p.back}, with reversed spin. Replaces {p.edge} by {p.flp[2].fork}. Equivalent to {Flip1(Flip2(p)) = p.flp[2].flp[1]}. */ Place_t OPrev(Place_t s); Place_t Flip12(Place_t p); /* "Previous edge around the origin". The inverse of {ONext}. Equivalent to {Flip2(Flip1(p)) = p.flp[1].flp[2]}. */ Place_t NextEK(Place_t p, int k); /* Returns {NextE^k(p)}. If {k} is negative, returns {PrevE^(-k)(p)}. */ Place_t NextFK(Place_t p, int k); /* Returns {NextF^k(p)}. If {k} is negative, returns {PrevF^(-k)(p)}. */ /* FLIP-DUAL OPERATORS */ Place_t Srot(Place_t p); /* "D&L pair rotation". In D&L's terms, exchanges the two components of {p.pair}, and then reverses the spin of {p.edge} (i.e. the flow of {p*.edge}). Equivalent to {Spin(Dual(p)) = p*.flp[3] = p.flp[0]*}. Observe that {Srot(Srot(p)) = Clock(p)}. */ Place_t Tors(Place_t p); /* "D&L reverse pair rotation". The inverse of {Srot}. Equivalent to {Dual(Spin(p)) = p.flp[3]* = p*.flp[0] = Spin(Clock(Dual(p))).}. Observe that {Tors(p) = Srot(Srot(Srot(p)))}. */ /* DATA POINTERS For each place {p}, the data structure maintains four variables, the /element slots/, {p.data[0..3]}, which can be set by the user and are conceptually associated to the four vertices of the chip {p.s.knt[0..3]}. pointer/. /wall info/, which can be set by the client to arbitray pointers. The two records are shared between the places {p}, {p.flp[0]}, {p.flp[3]}, and {p.flp[0].flp[3]}, but may be different for two places on the same edge or wall. The edge info of {p} is the wall info of {p*}, and vice-versa. */ typedef void *EdgeWallInfo_t; void SetEdgeInfo(Place_t p, EdgeWallInfo_t n); /* Set the {edge} field of {p} to {n}. */ void SetWallInfo(Place_t p, EdgeWallInfo_t n); /* Set the {wall} field of {p} to {n}. */ void SetRingEdgeInfo(Place_t p, EdgeWallInfo_t n); /* Does {SetEdgeInfo(q,n)} for all places {q} in the edge ring of {p}. */ void SetRingWallInfo(Place_t p, EdgeWallInfo_t n); /* Does {SetWallInfo(q,n)} for all places {q} in the wall ring of {p}. */ /* TUPLES OF PLACES */ typedef struct TwoPlaces_t { Place_t p[2]; } TwoPlaces_t; typedef struct FourPlaces_t { Place_t p[4]; } FourPlaces_t; typedef struct SixPlaces_t { Place_t p[6]; } SixPlaces_t; typedef struct EightPlaces_t { Place_t p[8]; } EightPlaces_t; typedef struct TwelvePlaces_t { Place_t p[12]; } TwelvePlaces_t; typedef struct TwentyPlaces_t { Place_t p[8]; } TwentyPlaces_t; typedef struct FiveByTwoPlaces_t { Place_t p[5][2]; } FiveByTwoPlaces_t; typedef struct TwelveByFivePlaces_t { Place_t p[12][5]; } TwelveByFivePlaces_t; /* Fixed-length tuples of places. */ vec_typedef(TwoPlaces_vec_t,TwoPlaces_vec,TwoPlaces_t); vec_typedef(FourPlaces_vec_t,FourPlaces_vec,FourPlaces_t); vec_typedef(SixPlaces_vec_t,SixPlaces_vec,SixPlaces_t); /* Arbitrary-length vectors of fixed-length tuples of places. */ /* ENUMERATION TOOLS */ typedef Place_t (*StepFunc_t)(Place_t p); /* A function from places to places. */ typedef bool_t (*VisitFunc_t)(Place_t p); /* A client-provided place visitation procedure. */ /* PLACE HASHING */ uint PHash(Place_t p); /* A hash function that maps places to pseudo-random unsigned integers. */ /* DISTINCTION AXIOMS In a proper facet-edge structure, one has {s.flp[i] != s} for any {s} and {i}. Also {s.flp[i].flp[j] != s} for any {i,j} such that {|i-j| >= 2}. The chips {s} and {t = s.flp[i]} specify the same sequence of elements of {M} except possibly for the element of dimension {i}; that is, {t.elm[j] == s.elm[j]} for all {j != i}. In a proper facet-edge structure, the the local orientations of {X} implied by {s} and {t} *always disagree* when compared across the shared wall of type {0..3}\{i}. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/OctfEnum.h #ifndef OctfEnum_H #define OctfEnum_H // #TIMESTAMP /* Last edited on 2007-01-31 09:10:54 by stolfi */ /* The Facet-Edge data structure for representing the topology of 3D maps. */ #define OctfEnum_H_copyright \ "Copyright © 1998 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE #include #include #include #include #include /* DATA STRUCTURE ENUMERATION A /place enumeration procedure/, such as all the {EnumXXX} functions below, starts from a given set of /root places/, and locates all places that can be reached from them by a chain of zero or more /steps/, in all possible combinations. Each procedure also /visits/ some of the places found during this process. Visiting a place means passing it to caller for arbitrary processing (see {VISIT-FUNCTIONS} below) and/or saving it in a {Place_vec_t} array provided by the caller (see {VISITATION LISTS} below). An enumeration procedure never visits the same place more than once, but may visit only a proper subset of the places it found --- e.g.only one place on each wall of the map, or only one cell among those that are incident to a given vertex. */ /* STEP-FUNCTIONS Each step of the enumeration consists of following some /step-func/, a function that maps places to places --- such as {Flip1}, {Flip23}, {NextF}, {ONext} etc.. A step-func needs not be one-to-one, and may even take a place in {M} to a place in {M*}, or to a place that is not connected to {p} by any sequence of {flp[i]} and {*} operations. The general enumeration procedures {EnumRing} and {EnumOrbits} use step-funcs provided by the caller. Other {EnumXXX} procedures use hard-wired step-funcs. */ /* VISIT-FUNCTIONS The {EnumXXX} procedures below generally take the address of a /visit-func/ (a {VisitFunc_t} parameter) to process each place found in the enumeration. The visit-func may return TRUE to abort the enumeration, or FALSE to let it continue. Unless noted otherwise, the {EnumXXX} procedure itself will return TRUE iff any visit-func call returned TRUE. (The visit-func should not try to abort the enumeration with a long jump, since doing so will create a storage leak and may even leave the structure in an invalid state.) A {NULL} visit-func is treated as a no-op that always returns {FALSE}. */ /* VISITATION LISTS The {EnumXXX} procedures below generally take a parameter {vP} of type {Place_vec_t*}. If {vP} is not {NULL}, the procedure will append to {vP}, *after* the current elements {vP->e[0..vP->ne-1]}, the places that were visited, in order of visitation. This applies even to virtual visits by a {NULL} visit-func. On the other hand, the procedure does not store in {*vP} any intermediate places that were used to reach the visited places but were not themselves visited. If the enumeration was aborted because a call to the visit-func returned TRUE, then {vP->e[vp->ne-1]} will be the argument of that call. In particular, the caller may pass the address of an empty {place_vec_t}, with {vP->e == NULL} and {vP->ne == 0}. (Note that this is different from passing {vP == NULL}.) The count {vP->ne} is updated to the number of places visited. The storage area {*(vP->e)} is expanded as needed, and trimmed at the end of the enumeration to hold precisely {vP->ne} places. */ /* THREAD-(UN)SAFETY Since the {EnumXXX} procedures modify the facet-edge data structure (by renumbering the places visited), there must never be more than one call to them excuting at any time. In particular, the visit-func shoud not try to call any {EnumXXX} procedure itself. */ /* VIEW-PRESERVING ENUMERATIONS A step-func {stp} is /view-preserving/ if {p.M == p.stp.M} for all {p}. In that case, every place {p} found in the enumeration satisfies {p.M == r.M} for some root place {r}. Thus, if all roots are on the same map, only places on that map will be visited. Of course, the places on the other map can be obtained by applying `{*}' to the visited places. All the wired-in steps used by the {EnumXXX} procedures below are view-preserving. */ /* EVEN AND ODD PATHS A step-func {stp} is /orientation-preserving/ if no place {p} is oddly connected to {p.stp}. (Note that this is a weaker requirement than `{p} and {p.stp} are evenly connected for every {p}'.) If {Y} is an orientable connected component of the space {X}, then any enumeration that starts from some root {r} on {Y} and uses only orientation-preserving steps will only visit places that determine the same orientation on {Y} as {r}. In particular, if a place {p} is visited, then {p.flp[i]} is not visited, for any {i}; and vice-versa. In this case, the places with opposite orientation can be be obtained by applying any {flp} operation to the visited places. On the other hand, if the the starting root {r} lies on a non-orientable connected component {Y} of {X}, then both {p} and {p.flp[i]} may be visited, for some {p} and {i}. Ditto if the given root set contains two places that are oddly-connected to each other. Some of the {EnumXXX} procedures below use only orientation-preserving steps, but some don't. */ /* GLOBAL ENUMERATION */ bool_t EnumPlaces(Place_vec_t root, VisitFunc_t visit, Place_vec_t *vP); /* Enumerates all places that are evenly-connected to the places {root.e[0..root.ne-1]}. */ bool_t EnumElems(Place_vec_t root, uint dimObj, VisitFunc_t visit, Place_vec_t *vP); /* Finds all places which are evenly reachable from the {root} places, and visits exactly one place on every map element of dimension {dimObj}. At most one of the places {p} and {p.flp[i]} will be visited, for any {p} and any {i} distinct from {dimObj}. This is true even if the manifold is not orientable and/or there are oddly-connected places among the roots. */ /* ENUMERATION OF ELEMENT STARS The following procedures restrict the enumeration to places on a specified set of elements, the /pivots/ of the enumeration. The pivots are the elements of the root places that have a specified dimension {dimPiv}. Thus, a place {p} will be visited only if it is reachable from some root place {r = root[i]}, and has {p.elt[dimPiv] == r.elt[dimPiv]}. If {dimPiv} is 3, for example, the pivots are the cell elements of the root places, and the enumeration will be restricted to places on those cells. If {dimPiv} is 1, the pivots are the nodes of the root places. And so on. */ bool_t EnumPlacesOfElem(Place_vec_t root, uint dimPiv, VisitFunc_t visit, Place_vec_t *vP); /* Visits all places on the pivot elements that are evenly reachable from the root places. */ bool_t EnumIncidencesOfElem(Place_vec_t root, uint dimPiv, uint dimObj, VisitFunc_t visit, Place_vec_t *vP); /* Enumerates all places on each pivot element {e} that are evenly reachable from the root places. It then calls {visit(q)} once for each element {f} of dimension {dimObj} among those places, and for each time that {f} bounds or incides on {e}; where {q} is some place on {e} and {f}. More precisely, the procedure never enumerates two places {p} and {q} if one is reachable from the other by an even number of {flp[j]} steps where {j} is distinct fron {dimPiv} and {dimObj}. However, it may visit both {p} and {q} if the manifold is not orientable or there are two or more oddly-connected roots. */ bool_t EnumElemsOfElem(Place_vec_t root, uint dimPiv, uint dimObj, VisitFunc_t visit, Place_vec_t *vP); /* Enumerates all places on each pivot element {e} that are evenly reachable from the root places. It then visits exactly one place {q} on each element {f} with dimension {dimObj} that occurs among those places. At most one of the places {p} and {p.flp[i]} will be visited, for any {p} and any {i} distinct from {dimPiv} and {dimObj}. This is true even if the manifold is not orientable and/or there are oddly-connected places among the roots. */ /* GENERAL ENUMERATION OF PLACE RINGS */ bool_t EnumRing(Place_t p, StepFunc_t step, VisitFunc_t visit, Place_vec_t *vP); /* Enumerates every place {q} reachable from {p} by zero or more calls to {step}, and calls {visit} on each, starting with {p} itself. See {VISITATION FUNCTIONS} above for details. If {vP} is not NULL, the procedure stores into {vP->e[0..vP->ne-1]} the places that were enumerated. See {VISITATION LISTS} above for details. The function {step} must eventually lead back to {p}, otherwise the procedure will loop forever. */ /* GENERAL STRATIFIED ENUMERATION */ bool_t EnumOrbits(Place_vec_t root, uint nS, StepFunc_t step[], VisitFunc_t visit[], Place_vec_t *vP); /* Enumerates all places that can be reached from the `root' places {root.e[0..root.ne-1]} by all possible sequences of calls to the functions {step[0..nS-1]}. For each new place found in the enumeration, including the starting ones, the procedure calls {visit[k](p)}, where {k} is some integer in {0..nS}. The enumeration stops when a call to {visit[k]} returns TRUE, or when all reachable places have been visited. The {EnumOrbits} procedure itself returns TRUE if any {visit} returned TRUE, and FALSE otherwise. If {QP} is not NULL, the procedure will set {*QP} to a descriptor of a newly allocated vector containing all places visited, in order of visitation. (If {QP->e} is not NULL, the procedure calls {free(QP->e)} before overwriting {*QP}). If {visit[k](p)} is called with {k < nS}, then {step[k]} was the last step along the path that led the procedure to {p} from the {root} places. If {k==nS}, it means that the path was empty --- that is, {p} is a {root} place that is not reachable from the earlier ones through {step} chains. The first call to {visit}, in particular, always has {k==nS}. The enumeration is stratified, with {step[i]} having higher enumeration priority than {step[j]} when {0 <= i < j <= nlevels-1}. More precisely: whenever {visit[k](p)} is called, the procedure will have visited every place that is reachable from a previously visited place by chains of steps of level less than {k}. After each call {visit[k](p)}, all places that are still unvisited and are are reachable from {p} through chains of steps with levels less than {k} will be visited next, before the next {visit[j]} call with {j >= k}. In particular, if {step[k]} is one-to-one, for all {k} in {0..nS-1}, then a call {visit[k](p)} means that {p} is the first place in a new orbit of the group generated by {{step[j] : j in 0..k-1 }}. moreover, that entire orbit will be visited next, before any subsequent {visit[j]} with {j>=k}. */ /* DEGREE FUNCTIONS */ uint DegreeOfWall(Place_t p); /* Returns the number of edges bounding the face of {p}, counting multiple incidences on the same edge. More precisely, returns the minimum positive number of {NextE} steps that take {p} to itself. */ uint DegreeOfEdge(Place_t p); /* Returns the number of faces incident to the edge of {p}, counting multiple incidences of the same face. More precisely, returns the minimum positive number of {NextF} steps that take {p} to itself. */ #define OctfEnum_H_author \ "This C interface was written jan/2007 by J.Stolfi." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/OctfRep.h #ifndef OctfRep_H #define OctfRep_H /* Internal representation of the facet-edge data structure. */ // #TIMESTAMP /* Last edited on 2007-01-29 01:22:11 by stolfi */ // #INCLUDE #include #include #include /* FACET-EDGE DATA RECORDS In a barycentric subdivision of a map on a (borderless) manifold, one always has {p.flp[0] != p}, {p.flp[0].flp[0] == p}, {p.flp[3] != p}, {p.flp[3].flp[3] == p}, {p.flp[0].flp[3] == p.flp[3].flp[0] != p}. It follows that the places in a map {M} are connected by {flp[0]} and {flp[3]} into discrete components (orbits) of size four, each comprising four /sibling chips/ {s00,s01,s10,s11}; where {flp[0]} (in {M}) swaps {s00<->s10} and {s01<->s11}, while {flp[3]} swaps {s00<->s01} and {s10<->s11}. The same holds for the places in the dual map {M*}. The the dual operator {*} establishes an isomorphism between each orbit on {M} and an orbit of {M*}, both based on the same four chips, except that the isomorphism exchanges the effects of {flp[0]} and {flp[3]}. The facet-edge data structure takes advantage of this fact to optimize the encoding of the {flp} operators. It uses a single data record to represent each of these four-chip groups and the eight places based on those chips. In this way, the operations {flp[0]} and {fpl[3]} stay on the same record. Only the operations {flp[1]} and [flp[2]} need to be encoded explicitly, by pointers between those records records. WEDGES Each data record can be viewed as representing a /wedge/ of the map {M}, the subset of {X} that comprises the four chips of such a group, plus every flag with {M}-type {{0,1,2}} or {{1,2,3}} that bounds two of those chips, and the link with {M}-type {{1,2}} {m} that bounds all four chips. A wedge {w} is therefore incident to exactly one edge {e = w.edge} of {M}, which is the union of two links with {M}-type {{0,1}} and one knot with {M}-type {{1}} that bound it. The wedge is also incident to exactly one edge {f*} of the dual map {M*}, comprising two links with {M}-type {{2,3}} and one knot with {M}-type {{3}}. The wall {f = w.wall} of {M} whose dual is {f*} is incident to {e} and bisects {w} and {f*}. Dually, the wall {e*} of {M*} is incident to the edge {f*} and also bisects {w} and {e}. The link {m} lies on the wall {f} and connects the centroids {e!} and {f!}; in fact, it is the intersection of the walls {e*} of {M*} and {f} of {M}. The wedge also incides on the two endpoints of its edge {e} (which may be the same node of {M}) and extends into the two cells separated by its wall {f} (which may be the same cell of {M}). */ typedef struct WedgeRec_t *Wedge_t; /* A {Wedge_t} is a pointer to record that represents a wedge of the two maps. */ vec_typedef(Wedge_vec_t,Wedge_vec,Wedge_t); /* A vector of pointers to wedge records. */ void WedgeInit(Wedge_t w); /* Initializes the contents of {*}. The {ca} pointers are set so that {w} is the single wedge of a new connected component {N} of the map, on a new connected component {Y} of {X}. The new subspace {Y} is homeomorphic to a three-sphere. The new map {N} will have one vertex, one loop edge, one wall and one cell. [!!! The comments said "two vertices"-- check!!!] */ Place_t MakeWedge(void); /* Allocates a new WedgeRec_t} record, initialize it with {WedgeInit}, and returns its base place. */ /* FROM WEDGES TO PLACES In order to identify a unique place in {M} or {M*}, the the facet-edge structure uses a pointer to a wedge record {w}, plus two /orientation bits/ that identify one chip {s} among the four chips contained in the wedge {w}, plus a /duality bit that selects between {M} and {M*}. The two orientation bits can be interpreted as specifying longitudinal orientations for the two edges of {M} and {M*} associated with {w}, namely {w.edge} and {w.wall*}. The duality bit specifies which of the two is *the* edge of {w}. */ #define MaxWedgeNum (UINT_MAX/8); /* The maximum wedge number allowed. */ typedef uint WedgeNum_t; /* Must be in [0..MaxWedgeNum]. */ /* ORIENTATION BITS */ typedef unsigned char SRBits_t; /* [0..7] Spin and Rotations bits */ typedef unsigned char RBits_t; /* [0..3] Rotations bits of */ typedef unsigned char OBit_t; /* [0..1] Orientation bit */ typedef unsigned char SBit_t; /* [0..1] Spin bit */ typedef unsigned char DBit_t; /* [0..1] Dual/Primal bit */ /* The meaning of these bits is relative, not absolute. (More on that below). */ Wedge_t PWedge(Place_t p); /* The record {w} that represents the wedge containing chip {p.s} (together with the other three sibling chips). */ SRBits_t PBits(Place_t p); /* The bits that identify the place {p} among the eight chips with the same wedge record as {p}. */ Place_t PlaceInWedge(Wedge_t w, SRBits_t srb); /* The place {p} on the wedge {w} with {SRBits(p) = srb}. */ Place_t WedgeBase(Wedge_t w); /* The `base' place on the wedge {w}, i.e. {PlaceInWedge(w,0)}. */ /* An {SRBits_t} value identifies a particular place within a wedge {w}, according to the following table (where {a == WedgeBase(w)}): | SRBits place OBit DBit SBit RBits | ----------------------------------------------- | 000 0 a 0 0 0 0 | 001 1 a.spin 0 0 1 0 | 010 2 a.srot 0 1 0 1 | 011 3 a.srot.spin 0 1 1 1 | 100 4 a.clock 1 0 0 2 | 101 5 a.clock.spin 1 0 1 2 | 110 6 a.tors 1 1 0 3 | 111 7 a.tors.spin 1 1 1 3 In general, the place {p = a.Srot^r.Spin^s}, for "r" in [0..3] and "s" in [0..1], has {SRBits(p) = 2r + s}. */ OBit_t OrientationBit(Place_t p); /* Orientation bit == "SRBits DIV 4". Reversed by "Clock", unchanged by "Spin", may be changed by "Srot". */ SBit_t SpinBit(Place_t p); /* Spin bit == "SRBits MOD 2". Reversed by "Spin". */ DBit_t DualBit(Place_t p); /* Dual bit == "SRBits DIV 2 MOD 2". Unchanged by "Spin" and "Clock", reversed by "Srot". */ RBits_t SrotBits(Place_t p); /* Rot bits == "SRBits DIV 2". Unchanged by "Spin", incremented twice by "Clock", either incremented or decremented by "Srot". */ /* CREATING AND RECLAIMING WEDGE RECORDS */ void DeleteWedge(Place_t p); /* Delete the wedge record of {p}. */ /* TOPOLOGY MODIFICATION */ void SpliceWalls(Place_t a, Place_t b); /* Merges or splits the wall-rings {F_a} and {F_b} of places {a} and {b}. */ void SpliceEdges(Place_t a, Place_t b); /* Merges or splits the edge-rings {E_a} and {E_b} of places {a} and {b}. */ void SetNextF(Place_t p, Place_t b); /* If {NextF(a) != b}, performs {SpliceWalls(a, PrevF(b))}. After this call {NextF(a)} will be equal to {b}. Valid whenever {SpliceWalls(a,PrevE(b))} is valid. */ void SetNextE(Place_t p, Place_t b); /* If {NextE(a) != b}, performs {SpliceEdges(a,PrevE(b))}. After this call, {NextE(a)} will be equal to {b}. Valid whenever {SpliceEdges(a,PrevE(b))} is valid. */ /* MELDING FACET-EDGE @PLACES */ void Meld(Place_t p, Place_t b); /* Meld {F_a} with {F_b} */ #define MaxPlaceNum ((MaxWedgeNum*8)-1) /* Maximum pair number */ typedef uint PlaceNum_t; /* [0..MaxPlaceNum] */ PlaceNum_t GetPlaceNum_t(Place_t p); /* == {PWedge(a).num * 8 + PBits(a)} */ /* ENUMERATING WEDGES */ Wedge_vec_t EnumWedges(Place_vec_t root, VisitFunc_t visit); /* Enumerates all wedges that can be reached from the places {root.e[0..root.ne-1]}. Calls {visit(p)} excatly once for each wedge, where {p} is the wedge's paseplace. Returns a list {W} of all the visited wedges. As a side effect, assigns sequential numbers to the {num} field of all visited wedges, so that {W[i]->num == i} for all {i} in {0..W.ne-1}. */ /* PRINTOUT */ void PrintPlace(FILE *wr, Place_t p, uint feWidth /* DF 1 */, bool_t nl /* DF FALSE */); /* Prints @place {a} as "m:r:s", where {m} is the serial wedge number, and {r,s} are such that {a == Spin^s(Srot^r(a0))}, where {a0} is the base @place of the wedge. The wedge number will be left-padded with spaces to {feWidth} bytes. if ((nl == TRUE the procedure adds the newline character in the end, else it not add the character. */ Place_t ReadPlace(FILE *rd, Wedge_vec_t *map); /* Reads from {rd} an @place in the {m:r:s} format used by {PrintPlace}. The {map} table is used to convert the wedge number {m} into a {Wedge_t} pointer.*/ void PrintWedge(FILE *wr, Wedge_t w, uint feWidth /* DF 1 */); /* Prints on {wr} the four places {NextF(Srot^r(b))}, where {b} is the base place of {w} and {r} ranges in {0..3}. Places are separated by one space. Each place is printed using {PrintPlace}, with wedge numbers left-padded to {feWidth} bytes. */ void ReadWedge(FILE *rd, Wedge_t w, Wedge_vec_t *map); /* Reads from {rd} four places {a[0..3]}, using {ReadPlace(rd, map)}. Then performs {SetNextF(Srot^r(b), a[r])}, where {b} is the base place of {w} and {r} ranges in {0..3}. */ /* WEDGE RECORD CONTENTS */ typedef struct NodeOrCellRec_t *NodeOrCell_t; typedef struct EdgeOrWallRec_t *EdgeOrWall_t; typedef struct NodeRec_t *Node_t; typedef struct EdgeRec_t *Edge_t; typedef struct WallRec_t *Wall_t; typedef struct CellRec_t *Cell_t; /* Pointer to records that describes elements of one of the maps, the /primal map/. [!!! Should be unified via duality !!!]. */ vec_typedef(Node_vec_t,Node_vec,Node_t); vec_typedef(Edge_vec_t,Edge_vec,Edge_t ); vec_typedef(Wall_vec_t,Wall_vec,Wall_t ); vec_typedef(Cell_vec_t,Cell_vec,Cell_t); /* Vectors of pointers to map element records. */ struct WedgeRec_t { Edge_t edge; /* Edge of the primal map that bounds this wedge. */ Wall_t wall; /* Wall of the primal map that bisects this wedge. */ Place_t next[4]; /* {w.next[RBits(p)] = NextF(p)}, if {p} is primal. */ bool_t marks1; /* [???]. */ bool_t marks2[2]; /* Used by {EnumNodes}, {EnumWedges}; indexed by {OrientationBit} [!!!] */ WedgeNum_t num; /* ID number of this wedge. */ uint ind; /* Used by {RenumberWalls}, {RenumberEdges} and {RenumberEdgesOutOfNodes} */ /* Fields used for barycentric subdivision: */ uint order; /* used for barycentric subdivision. */ uint order1, order2; /* used for barycentric subdivision. */ EightPlaces_t ca; /* Handles to the terahedron of barycentric subd map. */ /* Fields from {TriangulationWedgeRec_t}: */ NodeOrCell_t org[4]; /* Origin nodes (or containing cells) of the chips in wedge. */ bool_t mark3; /* Mark the wedge, used by TriangulationRefineT.*/ Node_t *vh; /* Medial node associated to wedge.*/ uint old; /* [???]. */ /* Fields from {JSTriWedgeRec_t}: */ bool_t refine; /* Mark bit used by RefineT. */ } WedgeRec_t; /* A {WedgeRec_t} record is associated to a wedge {w} of the two maps repesented by the facet-edge structure. The fields of the {WedgeRec_t} are defined with respect to a specific place on that wedge, the /base place/ -- one of the eight places whose chips are contained in {w}. If {p} is the base place of {w}, then {w.edge} represents the oriented edge {p.e[1]}, and {w.wall} represents the oriented wall {p.e[2]}. The topology of a map {M} is described by connecting {WedgeRec_t} records. In the current implementation, the base places of all wedges belong to the same map, the /primal map/. [!!! Change as follows: The base place of each record may belong to {M} or to {M*}. Hence each connection must specify the other wedge record and a specific place in it, among the 8 possible. !!!] */ // #default WedgeRec_t.num 0 // #default WedgeRec_t.marks1 FALSE // #default WedgeRec_t.ind 0 // #default WedgeRec_t.mark3 FALSE /* SPACES AND MAPS WITH VIRTUAL BORDERS A /pseudo-manifold with border/ is a compact space {X} where almost every point has a neighborhood that is either homeomorphic to {R^3} or to the closed half of {R^3} with a positive first coordinate. The /border/ of {X} is the closure in {X} of the set of points that have only neighborhoods of the second type. A /map with border/ is a map {M} on a pseudo-manifold with border. The border of {X} must necessarily be the union of nodes, walls and edegs of {M}. Moreover every element of {M} must bound some cell of {M}. If one must work with a map {M} with border, it is best to consider a borderless space {X'} that contains {|M|} as a subspace, and a map {M'} on {X'} that contains {M} as a submap; and then mark the elements of {M'} as /concrete/ (in {M}) or /virtual/ (not in {M}). That way, the stepping operators always yield a valid place and satisfy the usual identities. Note that any element of {M'} that is concrete must bound a cell of {M'} that is also concrete. The border of {|M|} is the union of all elements that are concrete but bound a virtual cell. */ /* SPACES AND MAPS WITH HARD BORDERS In theory the implementation allows {s.flp[i] == s}, which can be interpreted as the presence of a border in {X}. In that case, the flag {0..3}\{i} of {s} is contained in the border of {X}. However, this implementation is such that the chip {t = s.flp[i]} is always distict from {s} when {i} is 0 or 3. If {s.flp[1] == s}, then the border cuts across the cell {s.e[3]}. Ditto if {s.flp[2] == s}. The chips {s} and {t = s.flp[i]} specify the same sequence of elements of {M} except possibly for the element of dimension {i}; that is, {t.e[j] == s.e[j]} for all {j != i}. On the other hand, one may have {t.e[i] == s.e[i]} even when {t != s} (e.g. if {i == 0} and the edge {s.e[1]} is a loop. It is important to note that, when {t = s.flp[i]} is distinct from {s} --- in particular, when{X} is a (borderless) manifold --- the the local orientations of {X} implied by {s} and {t} *always disagree* when compared across the shared wall of type {0..3}\{i}. The facet-edge structure is implemented in such a way that that each {flp[i]} operation takes constant time. */ /* SELF-DUAL MAPS In a properly contructed facet-edge structure, the maps {M} and {M*} are completely distinct: each is a complete partition of {X}, and no element of one map is an element of the other map. In that case, the {flp[i]} operations always stay on the same map. However, the facet-edge structure can be modified in such a way that one can go from a place in {M} to a place in {M*} by a sequence of {flp} operations, without ever using the dual operator `*'. In that case the two maps merge into a single `pseudo-map' {M~}, that is no longer a partition of {X}, and all the theory above becomes invalid. If you feel the need to work with such structures, you should forget about the Facet-Edge struture, and use the Gem structure instead. */ #define OctfRep_H_AUTH \ " L. A. P. Lozada and J. Stolfi, UNICAMP." #define OctfRep_H_MODS \ " 1999 Modula-3 version {Octf.i3} created by L. Lozada,\n" \ " based on Modula-3 quad-edge module by R. M. Rosi\n" \ " and J. Stolfi.\n" \ " 2007-01-24 Converted to C and split off from {Octf.h} by J. Stolfi\n" #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/OctfData.h #ifndef OctfData_H #define OctfData_H // #TIMESTAMP /* Last edited on 2007-01-25 03:10:12 by stolfi */ // #INCLUDE // #INCLUDE #include #include #include /* DATA RECORDS FOR MAP ELEMENTS */ typedef struct NodeRec_t { uint num; /* Node number. */ /* Fields of {TriangulationNodeRec_t}: */ bool_t exists; /* FALSE for ghost nodes. [!!! Should be called {visible}? !!!] */ bool_t fixed; /* TRUE if position is fixed. */ bool_t xmark; /* Used by MakeCellTopology. */ frgb_t color; /* Color for painting. */ frgb_t transp; /* Transp. coefficient for painting. */ float radius; /* Node radius for drawing. */ char *label; /* Node label, useful in bar.sub. */ } NodeRec_t; /* A {NodeRec_t} record represents a vertex of the primal map. [!!! Unify with {CellRec_t} via duality !!!] */ // #default NodeRec_t.exists TRUE // #default NodeRec_t.fixed FALSE // #default NodeRec_t.xmark FALSE // #default NodeRec_t.color (frgb_t{0.0,0.0,0.0}) // #default NodeRec_t.transp (frgb_t{0.0,..}) // #default NodeRec_t.radius 0.020 // #default NodeRec_t.label "VV" typedef struct EdgeRec_t { Place_t pa; /* A place on the edge. */ uint num; /* Serial number of edge. */ uint dg; /* For computing degree of node */ bool_t exists; /* FALSE for immaterial edges */ bool_t degenerate; /* to mark as an element degenerate */ bool_t xmark; /* Mark used by MakeCellTopology */ frgb_t color; /* Color for drawing */ frgb_t transp; /* Transp. coeffs for painting */ float radius; /* radius for drawing */ NodeRec_t *node[2]; /* endpoints nodes */ int root; /* The root edge. */ bool_t marks2[2]; /* Used by Numberedges, ex: marks2[SpinBit(a)] associated to edge */ } EdgeRec_t; // #default EdgeRec_t.exists TRUE // #default EdgeRec_t.degenerate FALSE // #default EdgeRec_t.color (frgb_t{0.0,0.0,0.0}) // #default EdgeRec_t.transp (frgb_t{0.0,..}) // #default EdgeRec_t.radius 0.004 // #default EdgeRec_t.root (-1) typedef struct WallRec_t { Place_t pa; /* A place on this wall. */ uint num; /* Wall serial number. */ bool_t exists; /* FALSE for ghost walls */ bool_t xmark; /* Mark used by MakeCellTopology */ frgb_t color; /* Color for painting */ frgb_t transp; /* Transp. coeffs for painting */ Node_vec_t node; /* endpoints nodes */ bool_t degenerate; /* to mark an element as degenerate*/ int root; /* The root wall */ bool_t marks2[2]; /* Used by RenumberWalls, ex: marks2[DualBit(a)] associated to Wall */ } WallRec_t; // #default WallRec_t.exists TRUE // #default WallRec_t.degenerate FALSE // #default WallRec_t.color (frgb_t{1.0,1.0,0.20}) // #default WallRec_t.transp (frgb_t{0.7,0.7,0.7}) // #default WallRec_t.root (-1) typedef struct CellRec_t { uint num; /* Node number. */ /* Fields of {TriangulationCellRec_t}: */ bool_t exists; /* FALSE for ghost cells. */ bool_t ymark; /* Used by ?????. */ Node_vec_t *node; /* Nodes defining the cell. */ frgb_t color; /* Color for painting. */ frgb_t transp; /* Transp. coefficient for painting. */ int root; /* The "root" cell. */ /* Used by {JSTri.h}: [???] */ bool_t degenerate; /* Element is degenerate */ } CellRec_t; // #default CellRec_t.exists TRUE // #default CellRec_t.ymark FALSE // #default CellRec_t.color (frgb_t{1.0,..}) // #default CellRec_t.transp (frgb_t{1.0,..}) // #default CellRec_t.root (-1) // #default CellRec_t.degenerate FALSE Node_t MakeNode(void); Edge_t MakeEdge(void); Wall_t MakeWall(void); Cell_t MakeCell(void); /* These procedures create new unattached element records. They should be attached to the structure with {SetOrg}, {SetEdge}, etc.. */ /* ATTACHING MAP ELEMENTS TO THE FACET-EDGE STRUCTURE */ Edge_t PEdge(Place_t p); /* Returns the {Edge_t} assigned to the edge slot of {p} (or of {p*}, if {p} is on the dual map). [!!! should be dual-sensitive !!!] */ Wall_t PWall(Place_t p); /* Returns the {Wall_t} assigned to the wall slot of {p} (or of {p*}, if {p} is on the dual map). [!!! should be dual-sensitive !!!] */ NodeOrCell_t Org(Place_t p); /* Returns the element record that is currently stored in the `origin node' slot of of {p}. */ void SetOrg(Place_t p, Node_t n); /* Stores element record {n} in the `origin node' slot of {p}. */ void SetOrgAll(Place_t p, Node_t n); /* Does {SetOrg(t,n)} for all places {t} with the same origin node as {p}. Those are the places that can be reached from {p} by chains of {NextF}, {NextE}, and {Clock} steps. */ NodeOrCell_t Pneg(Place_t p); /* Returns the element record that is currently stored in the `negative cell' slot of {p}. */ void SetPneg(Place_t p, Cell_t n); /* Stores element record {n} in the `negative cell' slot of {p}. Same as {SetOrg(Dual(p),n)}. */ void SetPnegOfWall(Place_t p, Cell_t n); /* Does {SetPneg(t,n)} for all places {t} with the same wall and cell as {p} (i.e. on the {NextE} ring of {p}). */ void SetPnegOfNearbyWalls(Place_t p, Cell_t n); /* Sets to {n} the {Pneg} pointer of all places whose wall is the wall {f} of {p}, or one of the walls adjacent to {f} on the same negative cell as {p}. */ NodeOrCell_t Ppos(Place_t p); /* Returns the element record that is currently stored in the `positive cell' slot of {p}. */ void SetPpos(Place_t p, Cell_t n); /* Stores element record {n} in the `positive cell' slot of {p}. Same as {SetOrg(Clock(Dual(a),n) == SetOrg(Tors(a),n)}. */ void SetPposOfWall(Place_t p, Cell_t n); /* Does {SetPpos(t,n)} for all places {t} with same wall and cell as {p} (i.e. on the {NextE} ring of {p}). */ void SetPposQUX(Place_t p, Cell_t n); /* Set the places (12) belong to same positive cell {Ppos} equal to {n}. */ Node_t OrgV(Place_t p); /* The origin of {p}, narrowed to type {Node_t}. The place {p} must be on the primal map. [!!!] */ Node_t DesV(Place_t p); /* The destination of {p}, narrowed to type {Node_t}. The place {p} must be on the primal map. [!!!] */ Cell_t PnegP(Place_t p); /* The cell negative of {p}, narrowed to type {Cell_t}. The place {p} must be on the primal map. [!!!] */ Cell_t PposP(Place_t p); /* The positive cell of {p}, narrowed to type {Cell_t}. The place {p} must be on the primal map. [!!!] */ /* ELEMENT RENUMBERING The following procedures enumerate all places that are reachable from the places {pv.e[0..pv.ne-1]} by steps that preserve primality and orientation (namely {NextE}, {NextF}, and {Clock}.). Each procedure returns a vector with one pointer to each distinct element record found during the enumeration. */ Edge_vec_t RenumberEdges(Place_vec_t *pv); /* Collects and renumbers all (primal) edges reachable from {pv[0..pv.ne-1]}. */ Wall_vec_t RenumberWalls(Place_vec_t *pv); /* Collects and renumbers all (primal) walls reachable from {pv[0..pv.ne-1]}. */ Node_vec_t RenumberNodes(Place_vec_t *pv); /* Collects and renumbers all (primal) nodes reachable from {pv.e[0..pv.ne-1]}. */ Cell_vec_t RenumberCells(Place_vec_t *pv); /* Collects and renumbers all (primal) cells reachable from {pv.e[0..pv.ne-1]} by chains of {ONext}, {OPrev} and {Clock}, and assigns them distinct serial numbers from 0 up. Returns the number of nodes found. Uses the procedure {EnumNodes} of library {libm3triang}. */ Place_vec_t RenumberEdgesOutOfNodes(Place_vec_t *pv); /* Collects and renumbers all (primal) edges with the same origin nodes as the places {pv[0..pv.ne-1]}. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Map.h #ifndef Map_H #define Map_H // #TIMESTAMP /* Last edited on 2007-01-31 14:20:52 by stolfi */ /* Explicit representation of the topology of a 3D map. */ #define Map_H_copyright \ "Copyright © 2001 Universidade Estadual de Campinas (UNICAMP)" #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE /* ENUMERATION */ typedef struct ElemTableRec_t { Place_vec_t node; Place_vec_t edge; Place_vec_t wall; Place_vec_t cell; Wedge_vec_t wedge; /* one place for each wedge */ /* These fields are used by {JStri.h}: [???] */ /* uint der; */ /* Edge Ring Degree */ /* uint bdr; */ /* Where (0) indicates without boundary */ /* (1) indicates with boundary */ /* and (2) indicates that cells are octahedra */ } ElemTableRec_t; /* Explicit tables of elements of a 3D map. A {ElemTableRec_t} structure {top} describes a 3D map {N}, consisting zero or more connected components of the maps represented by the facet-edge structure. The structure is basically four tables {top.elem[d]}, for {d} in {0..3} that provide direct access to all {d}-dimensional elements of {N}. For data structure {top} to be valid, each data field {p.data[d]} of every place {p} on {N} must contain a pointer to the appropriate {d}-dimensional element record --- a {NodeRec_t}, {EdgeRec_t}, {WallRec_t}, or {CellRec_t}, respectively, for {d == 0,1,2,3}. There must be a distinct and unique element record for each map element. Moreover, the {num} fields of all {d}-element records of {N} must contain sequential integers from 0 to {n-1}, in any order; where {n} is the number of such elements in the map {N}. Finally, for each {d} in {0..3} and each {i} in {0..n-1}, the entry {p = top.elem[d].e[i]} must be a place on the {d}-element with number {i}; that is, one must have {p.data[d]->num == i}. Each component of {N} may come from {M} or {M*} indifferently. However, if a component {K} of {M} is included in {N}, its dual {K*} must not be. */ typedef ElemTableRec_t *ElemTable_t; ElemTableRec_t MakeElemTable(Place_vec_t root); /* This procedure renumbers the element records in the submap {N} that are reachable from the places {root.e[0..root.ne-1]}, and returns an {ElemTableRec_t} with one place on each element. */ void FreeMapData(ElemTableRec_t *top); /* This procedure reclaims all the storage associated with the map element table {top}, including the element data records and the tables {top->elem[0..3].e}. */ typedef struct TopoDict_t { uint_vec_t OldNodeNum; uint_vec_t OldEdgeNum; uint_vec_t OldWallNum; uint_vec_t OldCellNum; } TopoDict_t; /* CELL TOPOLOGY */ typedef struct CellElementTable_t { Place_vec_t vRef; /* One Place_t out of each node. */ Place_vec_t eRef; /* One Place_t on each edge. */ Place_vec_t fRef; /* One Place_t on the boundary of each wall. */ } CellElementTable_t; /* A data structure that lists all elements on the boundary of a cell {c} of the map. [!!! This should be just a {ElemTableRec_t} for the submap that comprises the cell's star !!!]. */ CellElementTable_t *MakeCellTopology(Place_t p); /* Returns the elements of the boundary of the cell Pneg(Dual(a))==Org(a). Note that `PWedge(a)->@{edge->?}' is an @{edge->?} of the dual map. */ bool_t TriviallyIsomorphic(ElemTableRec_t *ta, ElemTableRec_t *tb); /* True iff {ta} and {tb} are topologically isomorphic, with the trivial isomorphism (that is, if elements with same index have the same topological relationship in both). */ #define Map_H_author \ "C Interface created by J. Stolfi in jan/2007.\n" \ "Partly based on Modula-3 interfaces by L.A.P.Lozada (1999)\n"\ "and R.M.Rosi (1994)." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Random.h #ifndef Random_H #define Random_H // #TIMESTAMP /* Last edited on 2007-01-25 09:29:43 by stolfi */ /* Random number generators. */ #include typedef struct Random_t { } Random_t; /* !!! To be fleshed out. */ Random_t MakeRandomSource(int seed); /* Creates a new random number generator. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Mis.h #ifndef Mis_H #define Mis_H // #TIMESTAMP /* Last edited on 2007-01-28 01:11:36 by stolfi */ /* Miscellaneous utility procedures. */ #define Mis_H_author \ "Created 2000 by L. A. P. Lozada, based on 1996 procedures by" \ "R. M. Rosi and J. Stolfi." // #INCLUDE #include #include #include #include #include #include /* typedef unsigned int uint; */ /* vec_typedef(uint_vec_t,uint_vec,uint); */ /* A vector of unsigned integers. */ typedef r4_t Point; #define BoolChars ((char[]){'F', 'T'}) #define AlphaChars ((charset){'\t', '\n', '\r', '\f', ' ', 'A'..'Z', 'a'..'z'}) double ThrowDouble(Random_t *coins, double radius /* DF 0.20 */); /* Return one real value between [-radius, +radius]. */ void WritePoint4D(FILE *wr, r4_t *c); /* Write 4D point with {scientific} format. */ void WritePoint3D(FILE *wr, r3_t *c); /* Write 3D point with {scientific} format. */ void WritePoint2D(FILE *wr, r2_t *c); /* Write 2D point with {scientific} format. */ void WriteIntensity(FILE *wr, float r); /* Write one component color (real value) between 0-1. */ void WriteColor(FILE *wr, frgb_t *c); /* Write colors in RGB mode. */ void WriteRadius(FILE *wr, float r); /* Write one value Real. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/PZGeo3.h #ifndef PZGeo3_H #define PZGeo3_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ /* Miscellaneous geometry tools */ #define PZGeo3_H_author \ "Based on PZ_geo.h by H.C.G.Leităo and J.Stolfi, 1999-08." \ "Adapted by L.A.P.Lozada, 1999-2000." #include r3_t PZGeo3_LinearInterpolate(double t, double a, r3_t *pa, double b, r3_t *pb); /* Interpolates linearly the position at time {t} between points {pa} and {b}, assuming they have times {a} and {b}. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/PZGeo4.h #ifndef PZGeo4_H #define PZGeo4_H // #TIMESTAMP /* Last edited on 2007-01-25 10:08:52 by stolfi */ #define PZGeo3_H_author \ "Based on PZ_geo.h by H.C.G.Leităo and J.Stolfi, 1999-08." \ "Adapted by L.A.P.Lozada, 1999-2000." #include r4_t PZGeo4_LinearInterpolate(double t, double a, r4_t *pa, double b, r4_t *pb); /* Interpolates linearly the position at time {t} between points {pa} and {b}, assuming they have times {a} and {b}. */ void PZGeo4_HermiteInterpolate ( double t, double a, r4_t *pa, r4_t *va, double b, r4_t *pb, r4_t *vb, r4_t *p, r4_t *v ); /* Performs cubic Hermite interpolation for argument {t} given positions {pa} and {pb} and velocities {va} and {vb} at times {a} and {b}. Best used for {t} between {a} and {b}. */ r4_t PZGeo4_BSplineApproximation ( double t, double a, double b, r4_t *Pabc, double c, r4_t *Pbcd, double d, r4_t *Pcde, double e, r4_t *Pdef, double f ); /* Computes the position at time {t} of a cubic B-Spline curve with control points {Pabc}, {Pbcd}, {Pcde}, {Pdef}, and knot times {a},... {f}. Assumes {t} lies between {c} and {d}. */ r4_t PZGeo4_CubicBezier ( double t, r4_t *Pabc, r4_t *Pbcd, r4_t *Pcde, r4_t *Pdef ); /* Computes the position at time {t} of a cubic Bezier curve with control points {Pabc}, {Pbcd}, {Pcde}, {Pdef}. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Tools.h #ifndef Tools_H #define Tools_H // #TIMESTAMP /* Last edited on 2007-01-25 11:38:07 by stolfi */ /* Procedures for tests and others util procedures. */ #define Tools_H_author \ "Created by L. P. Lozada, 1999" // #INCLUDE // #INCLUDE void PrtDFR(Place_t p); /* Print the Degree Wall Ring of {p}. */ void PrtDER(Place_t p); /* Print the Degree @{Edge->?} Ring of {p}. */ void PrtDOV(Place_t p); /* Print the Degree of the node that is origin of {p}. */ void PrtDFE(Place_t p); /* Print the Degree Wall @{Edge->?} Ring of {a}. */ void PrtNextE(Place_t p); void PrtNextF(Place_t p); void PrtOrgNum(Place_t p); void PrtWallNum(Place_t p); void PrtEdgeNum(Place_t p); void PrtPnegNum(Place_t p); void PrtPposNum(Place_t p); void PrtNextPneg(Place_t p); /* Print the 12 places with the same Negative Cell, i.e the places belong to the same tetrahedral cell iff exits. */ void PrtNextPpos(Place_t p); /* Print the 12 places with the same Positive Cell, i.e the places belong to the same tetrahedral cell iff exits. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Triangulation.h #ifndef Triangulation_H #define Triangulation_H // #TIMESTAMP /* Last edited on 2007-01-31 14:15:05 by stolfi */ /* 3D triangulations represented with the facet-edge data structure. */ #define Triangulation_H_copyright \ "Copyright © 2001 Universidade Estadual de Campinas (UNICAMP)" #define Triangulation_H_author \ "Created by L. Lozada in 1999-2001???.\n" \ "Based on J. Stolfi and R. Marcone's 2D Triangulation.i3, ca. ????." #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE /* ELEMENT CREATION */ typedef struct FourNodes_t { Node_t v[4]; } FourNodes_t; FourNodes_t TetraNegNodes(Place_t p); /* The nodes of the tetrahedron {PnegP(a)}. */ FourNodes_t TetraPosNodes(Place_t p); /* The nodes of the tetrahedron {PposP(a)}. */ typedef struct FiveNodes_t { Node_t n[5]; } FiveNodes_t; FiveNodes_t TetraNegPosNodes(Place_t p); /* The nodes of the tetrahedra {PnegP(a)} and {PposP(a)}. */ typedef struct FourWalls_t { Wall_t f[4]; } FourWalls_t; FourWalls_t TetraWalls(Place_t p); /* The four walls of the tetrahedron {PnegP(a)}. */ typedef struct SixEdges_t { Edge_t e[6]; } SixEdges_t; SixEdges_t TetraEdges(Place_t p); /* The six edges of the tetrahedron {PnegP(a)}. */ typedef struct ThreeEdges_t { Edge_t e[3]; } ThreeEdges_t; ThreeEdges_t TriangEdges(Place_t p); /* The three edges of the wall of {p}. */ /* BORDER CHECKING */ bool_t EdgeIsBorder(Place_t p); /* TRUE if the edge of {p} belongs to the manifold's border (i.e. bounds a NULL cell). */ bool_t WallIsBorder(Place_t p); /* TRUE iff the wall of {p} belongs to the manifold's border. Same as {Ppos(p) == NULL) || (Pneg(p) == NULL}. */ /* MAP ELEMENT CONSTRUCTION */ void EmphasizeTetrahedron(Place_t a, Place_t b, uint n); /* Emphasizes the original elements of a tetrahedron produced by the MakeTetraTopo(order,order) procedure. */ EightPlaces_t MakeTetraTopo(uint nx, uint ny); /* Builds a topological tetrahedron subdivided radialy. The number of tetrahedra cells is {nx} by {ny}. Returns eight places at the corner wedges. */ Place_t Glue(Place_t a, Place_t b, uint n, bool_t setorg /* DF TRUE */); /* Glues two topological tetrahedra, by identification the {n} triangular walls on the topological boundary of tetrahedra. The places {a} and {b} must have the same {OrientationBit} and {SpinBit}. After teh call we will have {Pneg(a) == Pneg(b)}. The traversal of the topological boundary will be realized by quad-edge functions reduced to functions wedge. The identification of triangular walls will be done by the {Meld} procedure, removing the wedges on the chain {b} and updating the relations between nodes and cells. If {setorg == TRUE} then {SetOrgAll} is executed. */ TwelvePlaces_t GetTetraCorners(Place_t p); /* This procedure builds an array of 12 wedge @places, such all elements on the array have the same handness and the same negative poly. {Pneg}. The {p} in the argument must be a @place that represent one tetrahe- dron of $T$ (in the primal space). */ Place_vec_t *CollectTetrahedra(ElemTableRec_t *top); /* Returns a list {t} with one wedge on each tetrahedron from top in numerical order, with consistent orientations whenever possible. The wedges will be such that Pneg(t[i])->num == i. */ /* LOW-LEVEL ENUMERATION PROCEDURES */ void Collectwedges(Place_t p, Place_vec_t *re, uint *ne); /* Enumerates the @{edge->?}s of wall {a.wall} (with successive {NextE}s) and stores them in {re[0..NE-1]}. Also sets {NE} and (re)allocates {re^} as needed. */ void CollectCellWalls(Place_t p, Place_vec_t *rf, uint *nf); /* Enumerates the walls of cell {Pneg(a)} and stores them in {rf[0..nf-1]}. Also sets {nf} and (re)allocates {rf^} as needed. Assumes that the {xmark} bits of all wall records are FALSE. */ void CollectCellEdges(Place_t p, Place_vec_t *re, uint *NE, Place_vec_t *rf /* Working area */); /* Collects all edges of the cell {Pneg(a)}, returns their representative places in {re[0..NE-1]}. Also sets {NE} and (re)allocates {re^} as needed. Assumes all {xmark} bits are FALSE. The {rf} vector is a working area, expanded as needed; may be NULL initially. */ void CollectCellNodes(Place_t p, Place_vec_t *rv, uint *nv, Place_vec_t *rf /* Working area */); /* Collects all nodes of the cell {Pneg(a)}, returns their {OrgV}-representatives in {re[0..NE-1]}. Also sets {NE} and (re)allocates {re^} as needed. Assumes all {xmark} bits are FALSE. The {rf} vector is a working area, expanded as needed; may be NULL initially. */ /* INPUT/OUTPUT */ uint DegreeOfNode(Place_t p); /* Compute the degree of node that is Org(a) (i.e. the number of component @{edge->?}s incident to node). */ typedef struct AdjacencyMatrix_t { int rows; int cols; bool_t **e; } AdjacencyMatrix_t; AdjacencyMatrix_t *MakeAdjacencyMatrix(ElemTableRec_t *top); /* Builds the adjacency matrix for the map element table {top}. */ void GetVariableNodes(ElemTableRec_t *top, bool_vec_t *vr); /* Sets {vr[v] = TRUE} for every node {v} that is not fixed. */ /* GEOMETRIC TOOLS */ typedef r4_vec_t Coords_t; /* Coordinates for all {NodeRec_t}s in the structure. */ void InitCoords(Random_t *coins, Coords_t *c, float radius /* DF 1.0 */); /* Fills c with random coordinates in the range {[-radius __ +radius]}. */ Coords_t GenCoords(ElemTableRec_t *top); /* Returns a new {Coords_t} vector {v}, initialized with {InitCoords(&v, 1.0)}. */ void Displace(ElemTableRec_t *top, r4_t *d, Coords_t *c); /* Displaces all existing nodes by {d}. */ void Scale(ElemTableRec_t *top, double s, Coords_t *c); /* Scales the coordinates of all existing nodes by {s}. */ r4_t WallCross(Place_t p, Coords_t *c); /* A vector approximately perpendicular to {wall} field of {p}, this vector is computing by the mean of two perpendicular vectors (with orientation topological consistent) for two tetrahedrons inci- dents in this wall. Returns the unit vector if the wall has atributte {exists==FALSE}. */ r4_t WallNormal(Place_t p, Coords_t *c); /* Normal of {wall} field of {a}; same as {r4_Dir(WallCross(a, c))}. Returns an arbitrary unit vector if the wall has zero area. */ r4_t PolyCross(Place_t p, Coords_t *c); /* A vector approximately perpendicular to Pneg of {p}. Returns the unit vector if the cell has atributte {exists==FALSE}. */ r4_t PolyNormal(Place_t p, Coords_t *c); /* Normal of {Pneg(a)}; same as {r4_Dir(PolyCross(a, c))}. Returns an arbitrary unit vector if the wall has zero area */ r4_t EdgeCross(Place_t p, Coords_t *c); /* A vector approximately perpendicular to component edge of {p}, this vector is computing by the mean of perpendicular vectors (with orientation topological consistent) to all tetrahedrons incidents in this edge. Returns the unit vector if the edge has atributte {exists==FALSE}. */ r4_t EdgeNormal(Place_t p, Coords_t *c); /* Normal of component edge of {a}; same as {r4_Dir(EdgeCross(a, c))}. Returns an arbitrary unit vector if the edge has zero lenght. */ r4_t WallBarycenter(Place_t p, Coords_t *c); /* The barycenter of wall component of {p}. */ r4_t TetraBarycenter(Place_t p, Coords_t *c); /* The barycenter of the negative tetrahedron of {p}. */ r4_t NodeCross(Place_t p, Coords_t *c, ElemTableRec_t *top); /* A vector approximately orthogonal to the Org(a), whose length is proportional the volume of the cell defined by the {existing} neighbors of {Org(a)}. */ r4_t NodeNormal(Place_t p, Coords_t *c, ElemTableRec_t *top); /* Estimated normal at Org(a), considering only neighbors that exist; same as {r4_Dir(NodeCross(a, c))}. Returns an arbitrary unit vector if {NodeCross(a, c)} is zero. */ typedef struct Quadp { Place_t p[4]; } Quadp; typedef struct Quadv { Node_t v[4]; } Quadv; typedef struct Triv { Node_t v[3]; } Triv; typedef struct Trip { Place_t p[3]; } Trip; vec_typedef(Quadv_vec_t,Quadv_vec,Quadv); /* A vector of {Quadv}s. */ Node_vec_t *Neighbors(Place_t p, ElemTableRec_t *top); /* Neighbor nodes of {v}, for any topology. */ Quadv_vec_t *StarOfNode(Place_t p, ElemTableRec_t *top); /* Return the node set that conform every tetrahedron belonging to star of OrgV(a). The node set is sorted such as, the first element is OrgV(a), the second is OrgV(NextE(a)), the third OrgV(PrevE(a)) and the las element is OrgV(PrevE(PrevF(a))). */ uint NumberPolyOfStar(Quadv_vec_t *qv); /* Return the number of cells that belong to star of OrgV(a). */ r4_vec_t *ComputeAllNodeNormals(ElemTableRec_t *top, Coords_t *c); /* Returns a vector with the result of NodeNormal applied to each node of {top}. */ r4_vec_t *ComputeAllEdgeNormals(ElemTableRec_t *top, Coords_t *c); /* Returns a vector with the result of EdgeNormal applied to each @{edge->?} of {top}. */ r4_vec_t *ComputeAllWallNormals(ElemTableRec_t *top, Coords_t *c); /* Returns a vector with the result of Wall Normal applied to each wall of {top}. */ r4_vec_t *ComputeAllCellNormals(ElemTableRec_t *top, Coords_t *c); /* Returns a vector with the result of PolyNormal applied to each polyhe- dron of {top}. */ /* GEOMETRIC AVERAGES */ /* In the following procedures, when {all == TRUE} the quantities are computed over all elements of the appropriate dimension; otherwise they are computed only over those elements with {existing == TRUE}. */ r4_t Barycenter(ElemTableRec_t *top, Coords_t *c, bool_t all); /* Returns the barycenter of all nodes. */ r4_t PartialBarycenter(Node_vec_t *v, Coords_t *c, bool_t all); /* Barycenter of the nodes {v[i]}. Previously called {NeighborBarycenter}. */ double MeanNodeDistance(ElemTableRec_t *top, Coords_t *c, r4_t *ctr, bool_t all); /* The average distance of nodes from {ctr}, in the root-mean-square sense; that is, {sqrt(sum(norm(c[v]-ctr)^2)/N)}. */ double MaxNodeDistance(ElemTableRec_t *top, Coords_t *c, r4_t *ctr, bool_t all); /* The maximum distance of a node from {ctr}. */ double MeanEdgeLength(ElemTableRec_t *top, Coords_t *c, bool_t all); /* The average length of edges, in the root-mean-square sense; that is {sqrt(sum(dist(c[org(e)], c[dst(e)])^2)/N)}. */ r4_t MeanCellNormal(ElemTableRec_t *top, Coords_t *c, bool_t all); /* The average of all tetrahedra normals, normalized to unit length. */ double MeanThickness(ElemTableRec_t *top, Coords_t *c, r4_t *ctr, r4_t *norm, bool_t all); /* Average node deviation from the hyperplane that passes through {ctr} and is orthogonal to {norm}, in the root mean square sense. */ void NormalizeNodeDistances(ElemTableRec_t *top, Coords_t *c, bool_t all); /* Shifts and scales all nodes so that they have barycenter (0,0,0,0) and unit mean square distance from the origin. The {all} parameter is used to compute the barycenter and the mean square distance. */ void NormalizeEdgeLengths(ElemTableRec_t *top, Coords_t *c, bool_t all); /* Shifts and scales all existing nodes so that they have barycenter (0,0,0,0), and the mean square length of existing @{edge->?}s is 1.0. The {all} parameter is used to compute the barycenter and the mean @{edge->?} length. */ /* INPUT/OUTPUT */ typedef struct TopCom_t { ElemTableRec_t *top; char *cmt; } TopCom_t; /* A {ElemTableRec_t} with a comment string. */ void WriteTopology(char *name, char *tag, ElemTableRec_t *top, char *cmt /* DF " " */); /* Writes {top}, and {cmt} to file disk in a format that can be read back. The file will have the given {name} with ".tp" appended. */ void WriteState(char *name, char *tag, ElemTableRec_t *top, Coords_t *c, char *cmt /* DF " " */); /* Writes the coordinates geometrics to file disk in a format that can be read back. The file will have the given {name} with ".st" appended. */ void WriteMaterials(char *name, char *tag, ElemTableRec_t *top, char *cmt /* DF " " */, bool_t ro_te /* DF FALSE */); /* Writes the materials properties to file disk in a format that can be read back. The file will have the given {name} with ".ma" appended. */ void WriteDualTopology(char *name, ElemTableRec_t *top, char *cmt /* DF " " */); /* Writes the dual of {top}, and {cmt} to file disk in a format that can be read back. The file will have the given {name} with ".tp" appended. */ void WriteStDe ( FILE *wr, Coords_t *c, /* Node coordinates */ Coords_t *Dc, /* Node coordinates derivates */ uint prec, /* DF 4; Significant figures to use for {c} and {Dc} */ char *cmt /* DF "" */ ); /* Writes the coordinates {c} and derivatives {Dc} to file {wr} in the ".sd" format. */ TopCom_t ReadToMa(char *name, bool_t ro_te /* DF FALSE */); /* A more general procedure to read two disk files created by {WriteTopology} and {WriteMaterials}. The files must have the given {name} with ".tp" and ".ma". */ Coords_t *ReadState(char *name); /* Reads a disk file created by {WriteState}. The file must have the given {name} with ".st" appended. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Tridimensional.h #ifndef Tridimensional_H #define Tridimensional_H // #TIMESTAMP /* Last edited on 2007-01-25 11:50:18 by stolfi */ /* Procedures that Write/Read a tridimensional state (.st3) and compute some 3D geometric operations. */ #define Tridimensional_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include #include #include typedef r3_vec_t Coords3D_t; typedef struct TetraData_t { uint p0, p1, p2, p3; r3x3_t A; double density, alpha, beta; } TetraData_t; vec_typedef(TetraData_vec_t,TetraData_vec,TetraData_t); /* A vector of {TetraData_t} */ r3_t Barycenter3D(ElemTableRec_t *too, Coords3D_t *c3); /* Returns the barycenter of all existing nodes. */ void Displace3D(ElemTableRec_t *top, r3_t *d, Coords3D_t *c3); /* Displaces all existing nodes by {d}. */ void Scale3D(ElemTableRec_t *top, double s, Coords3D_t *c3); /* Scales the coordinates of all existing nodes by {s}. */ double MeanNodeDistance3D(ElemTableRec_t *top, Coords3D_t *c3); /* The average distance of existing nodes from the origin, in the root-mean-square sense; that is, {sqrt(sum(norm(c3[v])^2, v IN VExist)) /|VExist|)}. */ void NormalizeNodeDistance3D(ElemTableRec_t *top, Coords3D_t *c3); /* Shifts and scales all existing nodes so that they have barycenter (0,0,0) and unit mean square distance from the origin. */ double TetraDet3D(uint u, uint v, uint w, uint x, Coords3D_t *c3); /* Signed determinant of the points {c3[u],c3[v],c3[w],c3[x]}, padded at the right with a column of {1}s. The absolute value of {TetraDet3D} is is six times the volume of the tetrahedron {u,v,w,x}, and the sign gives the handedness of the screw {u->v->w->x}.*/ bool_t WallIsSilhouette(Place_t p, Coords3D_t *c3); /* Return TRUE iff the projected wall associated to the {p} is a silhouette wall. */ int EdgeWindingNumber(Place_t p, Coords3D_t *c3); /* Returns the winding number of the tetrahedra incident to the edge. In a proper embedding, the number should be +1 or -1. */ r4_t ChoosePlaneThroughPoints(r3_t *u, r3_t *v); /* Chooses a plane through the points {u} and {v}. Returns the plane coefficients, the last one being the independent term. */ void FWriteState3D(FILE *wr, ElemTableRec_t *top, Coords3D_t *c3, char *cmt /* DF " " */); /* Writes the 3D geometric coordinates {c3->e[0..c3->ne-1]} to the previously opened file {wr}, in a format that can be read back by {FReadState3D}. The file {wr} will be flushed but will be left open. */ void WriteState3D(char *name, char *tag, ElemTableRec_t *top, Coords3D_t *c3, char *cmt /* DF { } */); /* Similar to {FWriteState3D}, but writes the data to a file "{name}{tag}.st3". */ Coords3D_t FReadState3D(FILE *rd); /* Reads from the previously opened file {rd} a vector of 3D geometric coordinates, in the format written by {WriteState3D}, and returns it. The file is left open. */ Coords3D_t ReadState3D(char *name, char *tag); /* Similar to {FReadState3D}, but the data is read from a disk file called "{name}{tag}.st3". */ void FWriteTetrahedra(FILE *wr, ElemTableRec_t *top, TetraData_vec_t *cell, char *cmt /* DF " " */); /* Writes the tetrahedron data {cell->e[0..dell->ne-1]} to the previously opened file {wr}, in a format that can be read back by {FReadTetrahedra}. The file {wr} will be flushed but will be left open. */ void WriteTetrahedra(char *name, char *tag, ElemTableRec_t *top, TetraData_vec_t *cell, char *cmt /* DF " " */); /* Similar to {}, but writes to a new disk file called "{name}{flage}.te". */ void WriteTetrahedron(FILE *wr, TetraData_t *t, uint nbase); /* Writes the data record of a single tetrahedron to {wr}. */ void ReadTetrahedron(FILE *rd, TetraData_t *t); /* Reads the data record single tetrahedron, produced by {WriteTetrahedron}. */ void FReadVectors(FILE *rd, uint n, Coords3D_t *pos); /* Reads a list of coordinates into {*pos}. */ #define Tridimensional_H_author \ "Created by L.A.P.Lozada ca. 1999.\n" \ "Some procedures are based on R. L. W. Liesenfeld's tools \n" \ "/Animaçăo dinâmica de corpos eásticos/, ca. ????.\n" \ "Modified by L. A. P. lozada on 2000-02-19." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Pov.h #ifndef Pov_H #define Pov_H // #TIMESTAMP /* Last edited on 2007-01-25 10:40:52 by stolfi */ /* Common procedures for POVray output. */ #define Pov_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" #define Pov_H_author \ "Created by L. P. Lozada, UNICAMP, 2000" \ "Based on tools by R.M.Rosi and J.Stolfi, UNICAMP, 199???" #include #include #include void WritePOVCoord(FILE *wr, double c); /* Writes a point coordinate in POVray format. */ void WritePOVPoint(FILE *wr, r3_t *p); /* Writes a 3D point in POVray format. */ void WritePOVColor(FILE *wr, frgb_t *cr); /* Writes a rgb color in POVray format. */ void WritePOVColorTransp(FILE *wr, frgb_t *cr, float tr, bool_t filter); /* Writes a rgb color with transparency {tr} in POVray format. */ void WritePOVCylinder ( FILE *wr, r3_t *o, r3_t *d, float radius, frgb_t *cr, float tr, bool_t filter, char *tag1 /* DF "" */, char *tag2 /* DF "" */ ); /* Defines a finite length cylinder without parallel end caps.*/ void WritePOVSphere ( FILE *wr, r3_t *p, float radius, frgb_t *cr, float tr, bool_t filter, char *tag1 /* DF "" */, char *tag2 /* DF "" */ ); /* Defines a sphere with center in {p} and radius {radius}. POVray has a highly optimized sphere primitive which renders much more quickly that the corresponding polynomial quadric shape. */ void WritePOVTriangle ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, frgb_t *cr, float tr, bool_t filter, char *tag1 /* DF "" */, char *tag2 /* DF "" */ ); /* Defines a triangle. Because triangle are perfectly flat surfaces it would requiere extremely large numbers of very smal triangles to appro- ximate a smooth, curved surface. */ void WritePOVTriangleTex ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, char *texture ); /* Defines a triangle as above but with a some predefined texture. */ void WritePOVSmoothTriangle ( FILE *wr, r3_t *a, r3_t *an, r3_t *b, r3_t *bn, r3_t *c, r3_t *cn, frgb_t *cr, float tr, bool_t filter ); /* Much of our perception of smooth surfaces is dependent upon the way ligth and shading is done. By artificially modifying the surface normals we can simulate a triangle to be a smooth curved surface. The SmoothTriangle primitive used the phong shading or interpolation of normals to calculate the surface normal for any point on the triangle based on normal vectors which you define for the three corners. These normal vectors are prohibitivily difficult to computed by hand. Therefore smoothtriangles are almost always generated by utility programs. */ void WritePOVSquare ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, r3_t *d, frgb_t *cr, float tr, bool_t filter ); /* Outputs a square formed by the union of two triangular walls, adjacent to one common edge. /\ d / \ a /____\ c \ / \ / b \/ */ void WritePOVTetrahedron ( FILE *wr, r3_t *u, r3_t *v, r3_t *w, r3_t *x, double du, double dv, double dw, double dx, frgb_t *cr, float tr, bool_t filter ); /* Builds a tetrahedron by the union of four triangular walls. to one common edge. v /|\ / | \ x /__|__\ w \ | / \ | / \|/ u */ void WritePOVPenta ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, r3_t *d, r3_t *e, frgb_t *cr, float tr, bool_t filter ); /* Define a pentagon build by the union of three triangular walls, adjacent to edge to one common edge. .b / \ c /___\a | /| | / | |/__| d e */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Tridimensional.c /* See {Tridimensional.h} */ // #INCLUDE #define Tridimensional_C_COPYRIGHT \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include #include #include #include #include #include #include #define TE_FILE_VERSION "99-08-25" #define ST_FILE_VERSION "99-08-25" #define EN_FILE_VERSION "99-08-25" #define ST3_FILE_VERSION "2007-01-27" /* File version stamps for ".te", ".st", ".en", and ".st3" files. */ r3_t Barycenter3D(ElemTableRec_t *top, Coords3D_t *c3) { r3_t B = (r3_t){{0, 0, 0}}; uint n = 0; int i; for (i = 0; i < c3->ne; i++) { Node_t v = OrgV(top->node.e[i]); if (v->exists){ r3_add(&(c3->e[i]), &B, &B); n++; } } r3_scale(1.0/n, &B, &B); return B; } double MeanNodeDistance3D(ElemTableRec_t *top, Coords3D_t *c3) { double S = 0.0; uint n = 0; int i; for (i = 0; i < c3->ne; i++) { Node_t v = OrgV(top->node.e[i]); if (v->exists) { S += r3_norm_sqr(&(c3->e[i])); n++; } } return sqrt(S/n); } void Displace3D(ElemTableRec_t *top, r3_t *d, Coords3D_t *c3) { int i; for (i = 0; i < c3->ne; i++) { if (OrgV(top->node.e[i])->exists) { r3_t *vc = &(c3->e[i]); r3_add(d, vc, vc); } } } void Scale3D(ElemTableRec_t *top, double s, Coords3D_t *c3) { int i; for (i = 0; i < c3->ne; i++) { if (OrgV(top->node.e[i])->exists) { r3_t *vc = &(c3->e[i]); r3_scale(s, vc, vc); } } } void NormalizeNodeDistance3D(ElemTableRec_t *top, Coords3D_t *c3) { r3_t b = Barycenter3D(top, c3); r3_neg(&b, &b); Displace3D(top, &b, c3); double s = MeanNodeDistance3D(top, c3); Scale3D(top, 1.0/s, c3); } int EdgeWindingNumber(Place_t p, Coords3D_t *c3) { Place_t q = p; int wnd = 0; /* Edge endpoints: */ r3_t u3 = c3->e[OrgV(p)->num]; r3_t v3 = c3->e[OrgV(Clock(p))->num]; r4_t u4 = (r4_t){{u3.c[0], u3.c[1], u3.c[2], 1.0}}; r4_t v4 = (r4_t){{v3.c[0], v3.c[1], v3.c[2], 1.0}}; r4_t pl = ChoosePlaneThroughPoints(&u3, &v3); do { /* Endpoints of opposite edge in tetrahedron: */ r3_t x3 = c3->e[OrgV(PrevE(q))->num]; r3_t y3 = c3->e[OrgV(PrevE(NextF(q)))->num]; r4_t x4 = (r4_t){{x3.c[0], x3.c[1], x3.c[2], 1.0}}; r4_t y4 = (r4_t){{y3.c[0], y3.c[1], y3.c[2], 1.0}}; bool_t pb = (r4_dot(&x4, &pl) <= 0.0); bool_t qb = (r4_dot(&y4, &pl) <= 0.0); if (pb != qb) { double det = r4_det(&u4, &v4, &x4, &y4); if (pb && (! qb)) { if (det > 0.0) { wnd++; } } else if ((! pb) && (qb)) { if (det < 0.0) { wnd--; } } } q = NextF(q); } while (q != p); return wnd; } r4_t ChoosePlaneThroughPoints(r3_t *u, r3_t *v) { r3_t d3; r3_sub(u, v, &d3); /* Find smallest coordinate in {d3}: */ uint iMin = 0; int i; for (i = 1; i < 3; i++) { if (fabs(d3.c[i]) < fabs(d3.c[iMin])) { iMin = i;} } r4_t u4 = (r4_t){{u->c[0], u->c[1], u->c[2], 1.0}}; r4_t v4 = (r4_t){{v->c[0], v->c[1], v->c[2], 1.0}}; r4_t w4; r4_axis(iMin, &w4); r4_t pl; r4_cross(&u4, &v4, &w4, &pl); return pl; } bool_t WallIsSilhouette(Place_t p, Coords3D_t *c3) { if ((Ppos(p) == NULL) || (Pneg(p) == NULL)) { return FALSE; } FiveNodes_t t = TetraNegPosNodes(p); uint un = t.n[0]->num; uint vn = t.n[1]->num; uint wn = t.n[2]->num; uint xn = t.n[3]->num; uint yn = t.n[4]->num; double d1 = TetraDet3D(un, vn, wn, xn, c3); double d2 = TetraDet3D(un, vn, wn, yn, c3); return d1*d2 >= 0.0; } double TetraDet3D(uint u, uint v, uint w, uint x, Coords3D_t *c3) { r4_t a = (r4_t){{c3->e[u].c[0], c3->e[u].c[1], c3->e[u].c[2], 1.0}}; r4_t b = (r4_t){{c3->e[v].c[0], c3->e[v].c[1], c3->e[v].c[2], 1.0}}; r4_t c = (r4_t){{c3->e[w].c[0], c3->e[w].c[1], c3->e[w].c[2], 1.0}}; r4_t d = (r4_t){{c3->e[x].c[0], c3->e[x].c[1], c3->e[x].c[2], 1.0}}; return r4_det(&a, &b, &c, &d); } void WriteState3D(char *name, char *tag, ElemTableRec_t *top, Coords3D_t *c3, char *cmt /* DF " " */) char *fileName = jsprintf("%s%s.st3", name, tag); FILE *wr = open_write(fileName, TRUE); FWriteState3D(wr, top, c3, cmt); fclose(wr); free(fileName); } void FWriteState3D(FILE *wr, ElemTableRec_t *top, Coords3D_t *c3, char *cmt /* DF " " */) { int vWidth = digits(top->node.ne - 1); /* Write the file header: */ filefmt_write_header(wr, "state3D", ST3_FILE_VERSION); /* Write the number of coordinates: */ fprintf(wr, "nodes = %d\n", top->node.ne); /* Write the file comment: */ if ((cmt != NULL) && ((*cmt) != 0)) { filefmt_write_comment(wr, cmt, '|'); } int ind = 0; /* Comment indentation. */ filefmt_write_comment(wr, "\nNode data:\n", ind, '|'); /* Write the node coordinates: */ int i; for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); /* state 3D */ fprintf(wr, "%*d ", vWidth, v->num); WritePoint3D(wr, &(c3->e[v->num])); fprintf(wr,"\n"); } filefmt_write_footer(wr, "state3D"); fflush(wr); } Coords3D_t ReadState3D(char *name, char *tag) char *fileName = jsprintf("%s%s.st3", name, tag); FILE *rd = open_read(fileName, TRUE); Coords3D_t c3 = FReadState3D(rd); fclose(rd); free(fileName); return c3; } Coords3D_t FReadState3D(FILE *rd) { /* Read and check the file header: */ filefmt_read_header(rd, "state3D", ST3_FILE_VERSION); /* Read the number of coordinates: */ uint nv = nget_uint32(rd, "nodes", 10); fget_eol(rd); /* Read the file comment: */ (void)filefmt_read_comment(rd, '|'); /* [!!! Should return it? !!!] */ /* Read the node coordinates: */ Coords3D_t c3 = r3_vec_new(nv); int j; for (j = 0; j < nv; j++) { int jj = fget_int32(rd); demand(j == jj, "node index mismathch in 3D state file"); r3_t *cv = &(c3.e[nv]); cv->c[0] = fget_double(rd); cv->c[1] = fget_double(rd); cv->c[2] = fget_double(rd); fget_eol(rd); } /* Read the node coordinates: */ filefmt_read_footer(rd, "state3D"); return c3; } void WriteTetrahedra(char *name, char *tag, ElemTableRec_t *top, TetraData_vec_t *cell, char *cmt /* DF " " */) char *fileName = jsprintf("%s%s.te", name, tag); FILE *wr = open_write(fileName, TRUE); FWriteTetrahedra(wr, top, cell, cmt); fclose(wr); free(fileName); } void FWriteTetrahedra(FILE *wr, ElemTableRec_t *top, TetraData_vec_t *cell, char *cmt /* DF " " */) { uint pWidth = digits(top->cell.ne - 1); filefmt_write_header(wr, "tetrahedra", TE_FILE_VERSION); fprintf(wr, "tetrahedra = %d\n", cell->ne); int ind = 0; /* Comment indentation. */ filefmt_write_comment(wr, cmt, ind, '|'); int i; for (i = 0; i < cell->ne; i++) { fprintf(wr, "%*d ", pWidth, i); WriteTetrahedron(wr, &(cell->e[i]), 0); } filefmt_write_footer(wr, "tetrahedra"); fflush(wr); } void WriteTetrahedron(FILE *wr, TetraData_t *t, uint nbase) { fprintf(wr, " %10.3f", t->A.c[0][0]); fprintf(wr, " %10.3f", t->A.c[0][1]); fprintf(wr, " %10.3f", t->A.c[0][2]); fprintf(wr, " "); fprintf(wr, " %10.3f", t->A.c[1][0]); fprintf(wr, " %10.3f", t->A.c[1][1]); fprintf(wr, " %10.3f", t->A.c[1][2]); fprintf(wr, " "); fprintf(wr, " %10.3f", t->A.c[2][0]); fprintf(wr, " %10.3f", t->A.c[2][1]); fprintf(wr, " %10.3f", t->A.c[2][2]); fprintf(wr, "\n"); fprintf(wr, " "); fprintf(wr, " %5d", nbase + t->p0); fprintf(wr, " %5d", nbase + t->p1); fprintf(wr, " %5d", nbase + t->p2); fprintf(wr, " %5d", nbase + t->p3); fprintf(wr, "\n"); fprintf(wr, " "); fprintf(wr, " %24.16e", t->density); fprintf(wr, " "); fprintf(wr, " %24.16e", t->alpha); fprintf(wr, " "); fprintf(wr, " %24.16e", t->beta); fprintf(wr, " "); fprintf(wr, "\n"); } void ReadTetrahedron(FILE *rd, TetraData_t *t) { t->A.c[0][0] = fget_double(rd); t->A.c[1][0] = fget_double(rd); t->A.c[2][0] = fget_double(rd); t->A.c[0][1] = fget_double(rd); t->A.c[1][1] = fget_double(rd); t->A.c[2][1] = fget_double(rd); t->A.c[0][2] = fget_double(rd); t->A.c[1][2] = fget_double(rd); t->A.c[2][2] = fget_double(rd); fget_eol(rd); t->p0 = fget_int32(rd); t->p1 = fget_int32(rd); t->p2 = fget_int32(rd); t->p3 = fget_int32(rd); fget_eol(rd); t->density = fget_double(rd); t->alpha = fget_double(rd); t->beta = fget_double(rd); fget_eol(rd); } void FReadVectors(FILE *rd, uint n, Coords3D_t *pos) { int i; for (i = 0; i < n; i++) { int ii = fget_int32(rd); demand(i == ii, "index mismatch in vector file"); int ch = fgetc(rd); demand(ch != EOF, "unexpected EOF"); pos->e[i].c[0] = fget_double(rd); pos->e[i].c[1] = fget_double(rd); pos->e[i].c[2] = fget_double(rd); fget_eol(rd); } } #define Tridimensional_C_author \ "Modula-3 version created by L.A.P.Lozada in 1999-2000.\n" \ "Based on Modula-3 procedures by R.W.L.Lieseneld and J.Stolfi.\n" \ "Modified by L. A. P. Lozada on 2000-02-19.\n" \ "Converted to C by J. Stolfi on 26-01-2007" // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Squared.h #ifndef Squared_H #define Squared_H // #TIMESTAMP /* Last edited on 2007-01-25 13:39:33 by stolfi */ /* Procedures to build several structures such as: n-gons, triangles and squares, cube, ball, bigcube (3D array of cube) with procedures for the glueing of two such complexes. */ #define Squared_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include void SetExWallsOfEdge(Place_t p, bool_t exists); /* Set the {exists} bit of every wall around the edge or {p}. */ void SetExEdge(Place_t p, bool_t exists); /* Set the {exists} bit of the edge of {p}. */ void SetExWall(Place_t p, bool_t exists); /* Set the {exists} bit of the wall of {p}. */ void SetExNode(Place_t p, bool_t exists); /* Set the node as non existing. */ #define Squared_H_author \ "Modula-3 version created by L. Lozada in 1999-2000. Revisions:\n" \ " 25-01-2007 : Exported {SetExEdge}, {SetExNode}, etc.\n" \ " 25-01-2007 : Split into separate modules for each solid.\n" \ " 24-01-2007 : Converted to C by J. Stolfi" #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Triangle.h #ifndef Triangle_H #define Triangle_H // #TIMESTAMP /* Last edited on 2007-01-25 14:06:02 by stolfi */ /* Procedures to build isolated triangular walls. */ #define Triangle_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include Place_t MakeTriangle(void); /* Make one triangular wall and set the three places with the same wall component. */ #define Triangle_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Square.h #ifndef Square_H #define Square_H // #TIMESTAMP /* Last edited on 2007-01-25 14:05:15 by stolfi */ /* Procedures to build isolatd square walls. */ #define Square_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include Place_t MakeSquare(void); /* Builds one square wall. The four places have the same wall component. */ #define Square_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Polygon.h #ifndef Polygon_H #define Polygon_H // #TIMESTAMP /* Last edited on 2007-01-25 14:04:32 by stolfi */ /* Procedures to build isolated {n}-sided polygons. */ #define Polygon_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include Place_t MakePolygon(uint n); /* Builds one {n}-gon wall. The {n} places have the same wall component. */ Place_vec_t MakePolygonFull(uint n); /* Builds one {n}-gon wall. The {n} places have the same wall component and this procedure return one place per side. */ void FixCoordsGon(uint order, Place_t p, ElemTableRec_t *top, Coords_t *c); #define Polygon_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Tetrahedron.h #ifndef Tetrahedron_H #define Tetrahedron_H // #TIMESTAMP /* Last edited on 2007-01-25 14:12:37 by stolfi */ /* Procedures to build tetrahedral polyhedra. */ #define Tetrahedron_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include FourPlaces_t MakeTetrahedron(void); /* Builds one tetrahedron such that the places have {Ppos==NULL}. Use in Baricentric Subdivision. */ #define Tetrahedron_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/FunnyBall.h #ifndef FunnyBall_H #define FunnyBall_H // #TIMESTAMP /* Last edited on 2007-01-25 14:26:47 by stolfi */ /* Building a funny ball-shaped complex [???] */ #define FunnyBall_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include FourPlaces_t MakeFunnyBall(void); /* Buils one cell with American football shape. This cell is the gluing scheme for obtain the "pseudomanifold" complex. */ Place_t GlueBall(Place_t a, Place_t b); /* Make the glueing of two simples 2-gon walls around of one common wall. The {a} and their adjacentes on the same wall component is killed. */ #define FunnyBall_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Cube.h #ifndef Cube_H #define Cube_H // #TIMESTAMP /* Last edited on 2007-01-25 14:26:38 by stolfi */ /* Procedures to build cubical polyhedra. */ #define Cube_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include SixPlaces_t MakeCube(void); /* Builds a cube from six squared walls. Returns one place from each wall. Wall 0 is the bottom, walls 1..4 are the sides, wall 5 is the top, as shown below. | +------+ | | | | | | | |5 | | +------+------+------+------+ | | | | | | | | | | | | | |1 |2 |3 |4 | | +------+------+------+------+ | | | | | | | |0 | | +------+ */ typedef struct EightNodes_t { Node_t v[8]; } EightNodes_t; EightNodes_t CubeNegNodes(Place_t p); /* The nodes of the negative cube of {a} ({PnegP(a)}). */ r4_t CubeBarycenter(Place_t p, Coords_t *c); /* The barycenter of the negative cube of {p}. */ Place_t GlueCube(Place_t p, Place_t b); /* Make the glueing of two simples cubes around of one squared wall common. The {p} and their adjacentes on the same wall component is killed. */ void FixCoordsCube(SixPlaces_t *ca, ElemTableRec_t *top, Coords_t *c); /* Set the node coordinates of the cube cell {ca} to the canonical geometry, the cube {[-1 _ +1]^3}. */ void PrintCubePlaces(Place_t p); /* Prints the 8 places with the same negative cell as {p}, assuming the cell is a cube. */ #define Cube_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/BigCube.h #ifndef BigCube_H #define BigCube_H // #TIMESTAMP /* Last edited on 2007-01-25 14:23:57 by stolfi */ /* Procedures that build arrays of cubical cells. */ #define BigCube_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include FourPlaces_vec_t Make1DCubearray(uint order); /* Build one row of cubes with order "order". */ TwoPlaces_vec_t Make2DCubeArray(uint order); /* Build one bidimensional array of cubes of order: {order x order}. */ TwoPlaces_vec_t MakeBigCube(uint order); /* Build one tridimensional array of cubic cellulas. Return two arrays of places of order: {order x order}, not eliminated by gluing procedure of columns of cubes. */ void SetCubeProperties(TwoPlaces_vec_t *a, uint n, ElemTableRec_t *top); /* Set the propiertes of a tridimensional array of cubic cells, such that it emphasis the elements of the external big cube. */ Place_t GlueBigCube(Place_t p, Place_t b, uint n); /* Make the glueing of two simples {bigcubes} around of one squared grid common wall. The {p} and their adjacentes on the same squared grid wall component is killed. */ TwoPlaces_vec_t BuildBigRawCube(uint order, bool_t original); /* Builds one tridimensional array of cubic cells with fixed geometry. if {original==TRUE} then the procedure emphasize the original elements on a cube. */ #define BigCube_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Pyramid.h #ifndef Pyramid_H #define Pyramid_H // #TIMESTAMP /* Last edited on 2007-01-25 14:04:57 by stolfi */ /* Pocedures to build {n}-sided pyramid polyhedra. */ #define Pyramid_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include Place_vec_t MakePyramid(uint n); /* Builds a pyramid with base as a n-gon wall, without cell information. */ Place_t MakeElongBip(uint n); /* Builds an elongated bipyramid. The icosahedron is obtained with n==5. */ Place_t BuildSimpleBipyr(uint n, bool_t open); Place_t BuildElongatedBipyr(uint n); void FixCoordsBipyramid(Place_t p, uint order, bool_t pyramid, ElemTableRec_t *top, Coords_t *c); /* Used by {MakeBipyramid.c}. If {pyramid} is true, the bottom apex is coplanar with the rim vertices at {Z=0}, so the base is flat. */ #define Pyramid_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Octahedron.h #ifndef Octahedron_H #define Octahedron_H // #TIMESTAMP /* Last edited on 2007-01-25 14:18:41 by stolfi */ /* Procedures to build octahedra. */ #define Octahedron_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include EightPlaces_t MakeOctahedron(void); /* Builds a topological octahedron, and return one place wedge {p[i]} for each wall of the octahedron. */ EightPlaces_t MakeOctahedronTriang(bool_t original); /* Builds a triangulated Octahedron, with eight tetrahedra, and return one place on each original wall. If {original==TRUE} the procedure emphasizes the original elements. */ #define Octahedron_H_author \ "C interface created by J. Stolfi, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Icosahedron.h #ifndef Icosahedron_H #define Icosahedron_H // #TIMESTAMP /* Last edited on 2007-01-25 14:21:26 by stolfi */ /* Procedures to build icosahedrons. */ #define Icosahedron_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include TwentyPlaces_t MakeIcosahedronTriang(bool_t original); /* Builds a triangulated Icosahedron, with twenty tetrahedra, and return one place on each original wall (i.e. 20). If {original == TRUE} the procedure emphasizes the original elements. */ TwentyPlaces_t OldMakeIcosahedronTriang(void); /* Prior version of the {MakeIcosahedronTriang}: Builds a triangualted icosahedron, with twenty tetrahedra, and return one place by original wall (i.e. 20). */ Place_t MakeIcosahedron(void); /* From MakePlatonic.c */ /* Builds an icosahedron as unique cell. */ #define Icosahedron_H_author \ "C interface created by J. Stolfi, jan/2007" #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Dodecahedron.h #ifndef Dodecahedron_H #define Dodecahedron_H // #TIMESTAMP /* Last edited on 2007-01-25 14:17:50 by stolfi */ /* Procedures to build dodecahedra (regular polyhedra 12 pentagonal faces). */ #define Dodecahedron_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include Place_t MakeDodecahedron(void); /* [!!! Compatibilize with other platonic builders.] */ /* Builds a dodecahedron as unique cell. */ #define Dodecahedron_H_author \ "Created by J. Stolfi, UNICAMP, jan/2007." #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/TriangulatedDodecahedron.h #ifndef TriangulatedDodecahedron_H #define TriangulatedDodecahedron_H // #TIMESTAMP /* Last edited on 2007-01-25 14:17:50 by stolfi */ /* Procedures to buils triangulated dodecahedra (semi-regular polyhedra with 60 triangular faces). */ #define TriangulatedDodecahedron_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE #include #include TwelveByFivePlaces_t MakeTriangulatedDodecahedron(bool_t original); /* Builds a triangulated dodecahedron, trough the automatic gluing of 60 tetrahedra. If {original==TRUE} the procedure emphasize the original elements. */ TwelveByFivePlaces_t TriangulatedDodecahedron2(void); /* [!!! Return type was {Free_vec_t}.] */ /* Build a triangulated dodecahedron, as the gluing of sixty tetrahedra, the gluings are done manually one to one (not automatically). */ #define TriangulatedDodecahedron_H_author \ "C interface created by J. Stolfi, jan/2007" #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Octf.c /* See {Octf.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-25 10:02:01 by stolfi */ // #INCLUDE #include #include #include #include #define Octf_C_copyright \ "Copyright © 1998 Universidade Estadual de Campinas (UNICAMP)" void SetEdgeInfo(Place_t p, EdgeWallInfo_t n) { PWedge(p)->edge = n; } void SetWallInfo(Place_t p, EdgeWallInfo_t n) { PWedge(p)->wall = n; } void SetRingWallInfo(Place_t p, EdgeWallInfo_t n) { Place_t t = p; do { SetWallInfo(t,n); t = NextE(t); } while (t != p); } void SetRingEdgeInfo(Place_t p, EdgeWallInfo_t n) { Place_t t = p; do { SetEdgeInfo(t,n); t = NextF(t); } while (t != p); } OBit_t OrientationBit(Place_t p) { return (PBits(p) >> 2); } SBit_t SpinBit(Place_t p) { return (PBits(p) & 1u); } DBit_t DualBit(Place_t p) { return ((PBits(p) >> 1) & 1u); } RBits_t SrotBits(Place_t p) { return ((PBits(p) >> 1) & 3u); } Place_t Dual(Place_t p) { return Spin(Srot(p)); } Place_t Srot(Place_t p) { return PlaceInWedge(PWedge(p), (PBits(p) + 2u + ((PBits(p) ^ 1u) << 2)) & 7u); } Place_t Spin(Place_t p) { return PlaceInWedge(PWedge(p), PBits(p) ^ 1u); } Place_t Clock(Place_t p) { return PlaceInWedge(PWedge(p), (PBits(p) + 4u) & 7u); } Place_t Tors(Place_t p) { return PlaceInWedge(PWedge(p), (PBits(p) + 6u + ((PBits(p) ^ 1u) << 2)) & 7u); } Place_t NextF(Place_t p) { SBit_t sbit = SpinBit(p); /* If {p} is spinned, must compute Spin(Clock(NextF(Clock(p)))): */ if (sbit) { p = Clock(p); } /* Now {SpinBit(p)} is 0, get {NextF} from stored pointers: */ RBits_t rbits = SrotBits(p); p = PWedge(p)->next[rbits]; /* Fix result if {p} was spinned: */ if (sbit) { p = Spin(Clock(p)); } return p; } Place_t NextE(Place_t p) { return Srot(NextF(Tors(p))); } Place_t PrevE(Place_t p) { return Clock(Srot(NextF(Srot(p)))); } Place_t PrevF(Place_t p) { return Clock(NextF(Clock(p))); } Place_t NextEK(Place_t p, int k) { if (k > 0) { do { p = NextE(p); k--; } while (k > 0); } else if (k < 0) { do { p = PrevE(p); k++; } while (k < 0); } return p; } Place_t NextFK(Place_t p, int k) { if (k > 0) { do { p = NextF(p); k--; } while (k > 0); } else if (k < 0) { do { p = PrevF(p); k++; } while (k < 0); } return p; } void SpliceWalls(Place_t a, Place_t b) { assert(b != Spin(NextF(a))); if (a!=b) { Place_t ta = NextF(a), tb = NextF(b); Place_t c = Clock(ta), d = Clock(tb); Place_t tc = NextF(c), td = NextF(d); if (SpinBit(a) == 0) { PWedge(a)->next[SrotBits(a)] = tb; } else { PWedge(a)->next[SrotBits(Clock(Spin(a)))] = Spin(d); } if (SpinBit(b) == 0) { PWedge(b)->next[SrotBits(b)] = ta; } else { PWedge(b)->next[SrotBits(Clock(Spin(b)))] = Spin(c); } if (SpinBit(c) == 0) { PWedge(c)->next[SrotBits(c)] = td; } else { PWedge(c)->next[SrotBits(Clock(Spin(c)))] = Spin(b); } if (SpinBit(d) == 0) { PWedge(d)->next[SrotBits(d)] = tc; } else { PWedge(d)->next[SrotBits(Clock(Spin(d)))] = Spin(a); } } } void SpliceEdges(Place_t a, Place_t b) { SpliceWalls(Dual(a), Dual(b)); } void Meld(Place_t a, Place_t b) { Place_t p = a, q = b; do { Place_t pp = PrevF(p); if (NextF(p)!=q) { SpliceWalls(p, PrevF(q)); assert(NextF(p) == q); } DeleteWedge(p); if (SpinBit(pp) == SpinBit(q)){ assert(NextF(pp) == q); } p = NextE(p); q = NextE(q); } while (p != a); } Place_t ONext(Place_t s) { return (DualBit(s)== 0 ? Clock(NextF(PrevE(s))) : PrevE(s)); } Place_t OPrev(Place_t s) { /* [!!! Comment in Octf.h was : If DualBit(s) == 0, then return Clock(PrevF(PrevE(s))) else return PrevE(s) */ /* [!!! Comment in Octh.c was : equivalent to ONext but change NextF by PrevF */ return Clock(PrevF(PrevE(s))); } void WedgeInit(Wedge_t w) { w->marks2[0] = FALSE; w->marks2[1] = FALSE; /* Place_t p = PlaceInWedge(w, 0); */ w->edge = NULL; /* [!!! WAS: MakeEdge(); w->edge->pa = p; !!!] */ w->wall = NULL; /* [!!! WAS: MakeWall(); w->wall->pa = p; !!!] */ /* Connect to itself: */ w->next[0] = PlaceInWedge(w, 0); w->next[1] = PlaceInWedge(w, 2); w->next[2] = PlaceInWedge(w, 4); w->next[3] = PlaceInWedge(w, 6); /* Fields from {TriangulationWedgeRec_t}: */ w->org[0] = NULL; /* For now, node of primal: C */ w->org[1] = NULL; /* For now, node of dual: C' */ w->org[2] = NULL; /* For now, node of primal: C */ w->org[3] = NULL; /* For now, node of dual: C' */ } Place_t MakeWedge(void) { Wedge_t w = (Wedge_t)notnull(malloc(sizeof(WedgeRec_t)), "no mem"); WedgeInit(w); return PlaceInWedge(w, 0); } void DeleteWedge (Place_t p) { SpliceWalls(p, PrevF(p)); SpliceWalls(Clock(p), PrevF(Clock(p))); free(PWedge(p)); } PlaceNum_t GetPlaceNum_t(Place_t p) { return (PWedge(p)->num << 3) | PBits(p); } void SetNextF(Place_t a, Place_t b) { if (NextF(a) != b) { SpliceWalls(a, PrevF(b)); } } void SetNextE(Place_t a, Place_t b) { if (NextE(a) != b){ SpliceEdges(a, PrevE(b)); } } void PrintPlace(FILE *wr, Place_t p, uint feWidth, bool_t nl /* DF FALSE */) { fprintf(wr, "%*u:%u:%u%s", feWidth, PWedge(p)->num, SpinBit(p), SrotBits(p), (nl ? "\n" : "")); } Place_t ReadPlace(FILE *rd, Wedge_vec_t *map) { int m = fget_int32(rd); assert((m >= 0) && (m < map->ne)); fget_match(rd, ":"); int s = fget_int32(rd); assert((s >= 0) && (s < 2)); fget_match(rd, ":"); int r = fget_int32(rd); assert((r >= 0) && (r < 4)); return PlaceInWedge(map->e[m], 2*r + s); } void PrintWedge(FILE *wr, Wedge_t w, uint feWidth /* DF 1 */) { int i; for (i = 0; i < 4; i++) { if (i > 0){ fputc(' ', wr); } PrintPlace(wr, w->next[i], feWidth, FALSE); } } void ReadWedge(FILE *rd, Wedge_t w, Wedge_vec_t *map) { int i; for (i = 0; i < 4; i++) { SetNextF(PlaceInWedge(w, 2*i), ReadPlace(rd, map)); } } #define INIT_QUEUE_SIZE 1024 /* ENUMERATING WEDGES */ Wedge_vec_t EnumWedges(Place_vec_t root, VisitFunc_t visit) { int nW = 0; Wedge_vec_t W = Wedge_vec_new(INIT_QUEUE_SIZE); /* The wedges visited so far are {W[0..nW-1]}. */ auto void VisitMarkAndStack(Wedge_t w); /* If {w} is unvisited, visits it, marks it as visited, appends it to the queue {W[0..nW-1]}. */ bool_t stop = FALSE; auto void EnumWedgesOfOne(Wedge_t w); /* Enumerates all unvisited wedges that can be reached from {w} by zero or more {next} links, and appends those wedges to {W[0..nW-1]}. */ /* Enumerate all roots: */ int i; for (i = 0; (i < root.ne) && (! stop); i++) { EnumWedgesOfOne(PWedge(root.e[i])); } /* We are done: */ return W; void EnumWedgesOfOne(Wedge_t w) { /* Save the queue's state: */ int nS = nW; /* Links of wedges {W[nS..nW-1]} still need following. */ VisitMarkAndStack(w); while ((nS < nW) && (! stop)) { /* Get a visited wedge {u}, follow its links: */ Wedge_t u = W.e[nS]; nS++; int r; for (r = 0; r < 4; r++) { w = PWedge(u->next[r]); VisitMarkAndStack(w); } } } void VisitMarkAndStack(Wedge_t w) { uint wn = w->num; if ((wn >= nW) || (W.e[wn] != w)) { /* First visit to wedge {w}: */ stop = visit(WedgeBase(w)); /* Add it to the visited wedge set: */ wn = nW; nW++; Wedge_vec_expand(&W, wn); W.e[wn] = w; /* Set the wedge's {num} field to its index in {pw}: */ w->num = wn; } } } #define Octf_C_author \ "The Modula-3 version of this source file was created in 1998" \ "by Luis Arturo Perez Lozada, UNICAMP, inspired on the " \ "Modula-3 implementation of the quad-edge data structure by " \ "J.Stolfi and R.M.Rosi (ca. 1994). " \ "It was converted to C and substantially revised in\n" \ "jan/2007 by J.Stolfi, who rewrote {EnumWedges}" \ "and unified it with {RenumberWedges}." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/OctfData.c /* See {OctfData.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-25 10:05:07 by stolfi */ // #INCLUDE // #INCLUDE #include #include Edge_t MakeEdge(void) { Edge_t e = (Edge_t)notnull(malloc(sizeof(EdgeRec_t)), "no mem"); e->marks2[0] = FALSE; e->marks2[1] = FALSE; return e; } Wall_t MakeWall(void) { Wall_t e = (Wall_t)notnull(malloc(sizeof(WallRec_t)), "no mem"); e->marks2[0] = FALSE; e->marks2[1] = FALSE; return e; } #define INIT_STACK_SIZE 1024 Edge_vec_t RenumberEdges(Place_vec_t *pv) { /* [!!! ???] Note: I change the SpinBit by DualBit for purpouses of gluing octahedra. */ Edge_vec_t estack = Edge_vec_new(INIT_STACK_SIZE); Place_vec_t pstack = Place_vec_new(INIT_STACK_SIZE); uint top = 0; /* top for stack "estack" */ uint nstack = 0; /* top for stack "pstack" */ auto void VisitAndMark(Place_t t); /* If {t} is unmarked: visit, mark, and stack it. */ void VisitAndMark(Place_t t) { Wedge_t w = PWedge(t); if ((w->ind < nstack) && (PWedge(pstack.e[w->ind]) == w)) { /* Wedge of {t} is already marked, not do nothing */ } else { /* Wedge of {t} is not marked. */ Edge_t e = PWedge(t)->edge; if (! e->marks2[DualBit(t)]) { /* Edge {e} is not marked; mark it and all edges of places adjacents to {t} */ Place_t tn = t; do { Edge_t en = PWedge(tn)->edge; en->marks2[DualBit(tn)] = TRUE; tn = NextF(tn); } while (tn != t); /* Save the edge {e} in {estack}: */ Edge_vec_expand(&estack,top);; estack.e[top] = e; /* Make {t} its entry place: */ e->pa = t; e->num = top; top++; } Place_vec_expand(&pstack,nstack); w->ind = nstack; pstack.e[nstack] = t; nstack++; } } uint seen = 0; /* Number of wedges whose childeren were looked at */ /* Stack the root places: */ int i; for (i = 0; i < pv->ne; i++) { VisitAndMark (pv->e[i]); } /* Enumerate edges, number them, collect in {estack}: */ while (seen < nstack) { Place_t s = pstack.e[seen]; VisitAndMark(NextF(s)); VisitAndMark(NextF(PrevE(s))); VisitAndMark(NextE(s)); VisitAndMark(PrevF(s)); seen++; } /* Erase all marks */ while (nstack > 0) { nstack--; Place_t b = pstack.e[nstack]; Place_t atn = b; do { PWedge(atn)->edge->marks2[DualBit(atn)] = FALSE; atn= NextF(atn); } while (atn != b); } /* Reclaim {pstack}, trim {estack}, and return it: */ Place_vec_trim(&pstack,0); Edge_vec_trim(&estack,top); return estack; } Wall_vec_t RenumberWalls(Place_vec_t *pv) { Wall_vec_t estack = Wall_vec_new(INIT_STACK_SIZE); Place_vec_t pstack = Place_vec_new(INIT_STACK_SIZE); uint top = 0; /* top for stack "estack" */ uint nstack = 0; /* top for stack "pstack" */ auto void VisitAndMark(Place_t t); /* If {t} is unmarked: visit, mark, and stack it. */ void VisitAndMark(Place_t t) { Wedge_t w = PWedge(t); if ((w->ind < nstack) && (PWedge(pstack.e[w->ind]) == w)) { /* Wedge of {t} is already marked, not do nothing */ } else { /* Wedge of {t} is not marked. */ Wall_t e = PWedge(t)->wall; /* if component wall of @place "t" not are marked, then */ if (! e->marks2[DualBit(t)]) { /* Wall {e} is not marked; mark it and all walls of places adjacents to {t} */ Place_t tn = t; do { Wall_t en = PWedge(tn)->wall; en->marks2[DualBit(tn)] = TRUE; tn = PrevE(tn); } while (tn != t); /* Save the wall {e} in {estack}: */ Wall_vec_expand(&estack,top); estack.e[top] = e; /* Make {t} its entry place: */ estack.e[top]->pa = t; e->num = top; top++; } Place_vec_expand(&pstack,nstack); w->ind = nstack; pstack.e[nstack] = t; nstack++; } } uint seen = 0; /* Number of wedges whose childeren were looked at */ int i; for (i = 0; i < pv->ne; i++) { VisitAndMark (pv->e[i]); } /* Enumerate walls, number them, collect in {estack}: */ while (seen < nstack) { Place_t s = pstack.e[seen]; VisitAndMark(NextF(s)); VisitAndMark(NextF(PrevE(s))); VisitAndMark(NextE(s)); VisitAndMark(PrevF(s)); seen++; } /* Erase all marks */ while (nstack > 0) { nstack--; Place_t b = pstack.e[nstack]; Place_t atn = b; do { PWedge(atn)->wall->marks2[DualBit(atn)] = FALSE; atn= PrevE(atn); } while (atn != b); } /* Reclaim {pstack}, trim {estack}, and return it: */ Place_vec_trim(&pstack,0); Wall_vec_trim(&estack,top); return estack; } Place_vec_t RenumberEdgesOutOfNodes(Place_vec_t *pv) { Place_vec_t estack = Place_vec_new(20); Place_vec_t pstack = Place_vec_new(20); uint top = 0; /* top for stack "estack" */ uint nstack = 0; /* top for stack "nstack" */ uint seen = 0; /* Wedges already seen. */ auto void VisitAndMark(Place_t t); /* If t is unmarked: visit, mark, and stack it. */ void VisitAndMark(Place_t t) { Wedge_t w = PWedge(t); if ((w->ind < nstack) && (PWedge(pstack.e[w->ind]) == w)) { /* wedge is already marked, do nothing */ } else { if (! w->marks2[DualBit(t)]) { /* mark PWedge(t)->edge and of all places with same edge as {t}. */ Place_t tn = t; do { PWedge(tn)->marks2[DualBit(tn)] = TRUE; tn = NextF(tn); } while (tn != t); /* Assign {w} a new serial number: */ w->edge->dg = top; /* Add {t} to the list {estack}: */ Place_vec_expand(&estack,top);; estack.e[top] = t; top++; } /* Add {t} to {pstack}: */ Place_vec_expand(&pstack,nstack); w->ind = nstack; pstack.e[nstack] = t; nstack++; } } /* Stack the root pointers: */ int i; for (i = 0; i < pv->ne; i++) { VisitAndMark(pv->e[i]); } /* Enumerate reachable places: */ while (seen < nstack) { Place_t s = pstack.e[seen]; if (DualBit(s) == 0) { VisitAndMark(ONext(s)); VisitAndMark(ONext(NextF(s))); } else { VisitAndMark(Clock(ONext(s))); VisitAndMark(Clock(ONext(NextF(s)))); } seen++; } /* Erase all marks */ while (nstack > 0) { nstack--; Place_t b = pstack.e[nstack]; Place_t atn = b; do { PWedge(atn)->marks2[DualBit(atn)] = FALSE; atn = NextF(atn); } while (atn != b); } /* Reclaim {pstack}, trim {estack} and return it: */ Place_vec_trim(&pstack,0); Place_vec_trim(&estack,top); return estack; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/OctfEnum.c /* See {OctfEnum.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-31 09:28:46 by stolfi */ // #INCLUDE // #INCLUDE #include #include #include #include #include #define OctfEnum_C_copyright \ "Copyright © 1998 Universidade Estadual de Campinas (UNICAMP)" bool_t EnumRing(Place_t p, StepFunc_t stp, VisitFunc_t visit, Place_vec_t *vP) { int nP = 0; /* Visited places are {vP->e[0..nP-1]}, if {vP != NULL}. */ Place_t q = p; bool_t stop = FALSE; do { stop = ( visit == NULL ? FALSE : visit(q)); if (vP != NULL) { Place_vec_expand(vP, nP); vP->e[nP] = q; nP++; } q = stp(q); } while ((q != p) && (! stop)); if (vP != NULL) { Place_vec_trim(vP, nP); } return stop; } #define INIT_QUEUE_SIZE 1024 bool_t EnumOrbits ( Place_vec_t root, uint nS, StepFunc_t step[], VisitFunc_t visit[], Place_vec_t *vP ) { Place_vec_t Q = (vP != NULL ? *vP : Place_vec_new(INIT_QUEUE_SIZE)); int nQ = 0; /* The places visited so far are {Q[0..nQ-1]}, in stratified order. */ auto void InitMarking(void); /* Initializes the tables used by {Marked} and {Mark}. */ auto bool_t Marked(Place_t p); /* TRUE iff place {p} has been marked (and therefore visited) in this call to {EnumOrbits}. */ auto void Mark(Place_t p); /* Marks {p} as visited. Assumes that {p} is not marked. */ auto void DoneMarking(void); /* Clears any permanent marks and reclaims storage used by {Marked} and {Mark}. */ bool_t stop = FALSE; /* Set to TRUE if any {visit[k]} returns TRUE. */ auto void EnumOrbitsOfOneRoot(Place_t p, int n); /* Enumerates all unvisited places that can be reached from {p} by zero or more calls to {step[k]} with {k} in {0..n-1}, and appends those places to {Q[0..nQ-1]}. */ /* Initialize the mark tables: */ InitMarking(); /* Enumerate all roots: */ int i; for (i = 0; (i < root.ne) && (! stop); i++) { EnumOrbitsOfOneRoot(root.e[i], nS); } /* Release the marking table storage: */ DoneMarking(); /* Return {Q}, or reclaim its space: */ if (vP == NULL) { free(Q.e); } else { Place_vec_trim(&Q, nQ); (*vP) = Q; } /* Return the aborted-enum indicator: */ return stop; /* MAIN PROCEDURE */ auto void EnumOrbitsOfOneRoot(Place_t p, int n); /* Like {EnumOrbits}, but restricted to one root, and excludes places already reached from previous roots. */ void EnumOrbitsOfOneRoot(Place_t p, int n) { if (! Marked(p)) { /* New place: visit it, mark it: */ if (visit[n] != NULL) { stop = visit[n](p); } Mark(p); /* Save the queue's state: */ int nX = nQ; /* Places {Q[nX..nQ-1]} still need {step[n-1]}. */ /* Add {p} to queue: */ Place_vec_expand(&Q, nQ); Q.e[nQ] = p; nQ++; if (stop || (n <= 0)) { return; } /* Enumerate lower orbits reachable from {p} by {step[n-1]}: */ while(TRUE) { EnumOrbitsOfOneRoot(p, n-1); if (stop || (nX >= nQ)) { return; } p = Q.e[nX]; nX++; p = step[n-1](p); } } } /* MARKING PROCEDURES */ int nW; ubyte_vec_t B; Wedge_vec_t W; /* The wedges visited so far are {W[0..nW-1]. For each {i} in {0..nW-1}, we must have {W[i]->num == i}. A place {p} has been visited iff {PWedge(p) = W[i]} for some {i} in {0..nW-1}, and the bit number {PBits(p)} of {B[i]} is set. */ void InitMarking(void) { B = ubyte_vec_new(INIT_QUEUE_SIZE); W = Wedge_vec_new(INIT_QUEUE_SIZE); nW = 0; /* No wedges have been seen yet. */ } bool_t Marked(Place_t p) { Wedge_t pw = PWedge(p); uint pn = pw->num; SRBits_t ps = PBits(p); return ((pn < nW) && (W.e[pn] == pw) && (((1 << ps) & B.e[pn]) != 0)); } void Mark(Place_t p) { Wedge_t pw = PWedge(p); uint pn = pw->num; uint8_t wB; /* Places on {pw} that have been visited earlier. */ if ((pn >= nW) || (W.e[pn] != pw)) { /* First place visitd on wedge {pw}, add it to the wedge set: */ pn = nW; nW++; Wedge_vec_expand(&W, pn); W.e[pn] = pw; /* Set the wedge's {num} field to its index in {pw}: */ pw->num = pn; wB = 0; } else { /* Wedge {pw} was visited before (at a different place): */ wB = B.e[pn]; } /* Mark place {p} as visited on {pw}: */ ubyte_vec_expand(&B, pn); B.e[pn] = wB | (1 << PBits(p)); } void DoneMarking(void) { /* There is no need to clear the wedge {num} fields. */ free(W.e); free(B.e); } } uint DegreeOfWall(Place_t p) { uint n = 0; Place_t s = p; do { n++; s = NextF(s); } while (s != p); return n; } uint DegreeOfEdge(Place_t p) { uint n = 0; Place_t s = p; do { n++; s = NextE(s); } while (s != p); return n; } bool_t EnumPlaces(Place_vec_t root, VisitFunc_t visit, Place_vec_t *vP) { /* Pick three functions {stp[0..2]} that generate all even walks. Then enumerate all places reachable by {}. */ StepFunc_t stp[3]; VisitFunc_t vis[4]; vis[0] = visit; stp[0] = &ONext; /* == Flip2.Flip1. */ vis[1] = visit; stp[1] = &SymNF; /* == Flip0.Flip2. */ vis[2] = visit; stp[2] = &NextF; /* == Flip3.Flip2. */ vis[3] = visit; /* == next root. */ return EnumOrbits(root, 3, stp, vis, vP); } /* ENUMERATING ELEMENTS */ bool_t EnumElems(Place_vec_t root, uint dimObj, VisitFunc_t visit, Place_vec_t *vP) { demand(dimObj <= 3, "invalid dimension for target elements"); demand(FALSE, "fix this code to return evenly reachable places only!!!"); /* Set {stp[0..3]} to {flp[0..3]}, permuted so that only {stp[3]} changes {p.elt[dimObj]}. So, each orbit of {stp[0..2]} corresponds to one element of dimension {dim}, and vice-versa. Then enumerate all orbits of {} that are reachable through {}. */ StepFunc_t stp[4]; stp[0] = &Flip0; stp[1] = &Flip1; stp[2] = &Flip2; stp[3] = &Flip3; /* Permute {stp[0..3]} so that {flp[dimObj]} is in {stp[3]}; */ /* Try to preserve some sort of dual symmetry. */ uint k = dimObj; /* Invariant: {stp[k] = flp[dimObj]}. */ if (k < 2) { /* Swap {stp[i]} with {stp[3-i]} for all {i}: */ StepFunc_t t; t = stp[0]; stp[0] = stp[3]; stp[3] = t; t = stp[1]; stp[1] = stp[2]; stp[2] = t; k = 3 - k; } /* Now the Invariant holds and {k} is {2} or {3}. */ if (k == 2) { /* Swap even and odd elements of {stp[0..3]}: */ StepFunc_t t; t = stp[0]; stp[0] = stp[1]; stp[1] = t; t = stp[3]; stp[3] = stp[2]; stp[2] = t; k = 3; } /* Now the Invariant holds and {k} is {2} or {3}. */ auto bool_t MyVisit(Place_t p); /* Appends {p} to {vP} and calls {visitNode(p)}. */ /* We should call {visit(p)} only after a {stp[3]} or a new root: */ VisitFunc_t vis[3]; vis[0] = NULL; vis[1] = NULL; vis[3] = NULL; vis[3] = MyVisit; vis[4] = MyVisit; int nP = 0; /* Visited places are {vP->e[0..nP-1]}, if {vP != NULL}. */ bool_t stop = EnumOrbits(root, 4, stp, vis, NULL); /* Trim the visit list to the true size: */ if (vP != NULL) { Place_vec_trim(vP, nP); } /* Return the abort indicator: */ return stop; bool_t MyVisit(Place_t p) { if (vP != NULL) { Place_vec_expand(vP, nP); vP->e[nP] = p; nP++; } return (visit != NULL ? visit(p) : FALSE); } } /* ENUMERATING THE STAR AND BOUNDARY OF AN ELEMENT */ bool_t EnumPlacesOfElem(Place_vec_t root, uint dimPiv, VisitFunc_t visit, Place_vec_t *vP) { demand(dimPiv <= 3, "invalid dimension for pivot elements"); /* We set {stp[0..1]} to generators of all the even walks that do not change {p.elt[dim]}. Then we enumerate all places reachable through {}. */ StepFunc_t stp[2]; switch(dimPiv) { case 0: /* Node: */ stp[0] = &Flip32; /* == Flip3.Flip2. */ stp[1] = &Flip21; /* == Flip2.Flip1. */ break; case 1: /* Edge */ stp[0] = &Flip32; /* == Flip3.Flip2. */ stp[1] = &Flip30; /* == Flip0.Flip3. */ break; case 2: /* Wall */ stp[0] = &Flip01; /* == Flip0.Flip1. */ stp[1] = &Flip03; /* == Flip0.Flip3. */ break; case 3: /* Cell */ stp[0] = &Flip01; /* == Flip0.Flip1. */ stp[1] = &Flip12; /* == Flip1.Flip2. */ break; default: assert(FALSE); } auto bool_t MyVisit(Place_t p); /* Appends {p} to {vP} and calls {visitNode(p)}. */ /* We should visit {p} only after a {stp[2]} or a new root: */ VisitFunc_t vis[3]; vis[0] = MyVisit; vis[1] = MyVisit; vis[2] = MyVisit; int nP = 0; /* Visited places are {vP->e[0..nP-1]}, if {vP != NULL}. */ /* OK, now enumerate the orbits: */ bool_t stop = EnumOrbits(root, 2, stp, vis, NULL); /* Trim the visit list to the true size: */ if (vP != NULL) { Place_vec_trim(vP, nP); } /* Return the abort indicator: */ return stop; bool_t MyVisit(Place_t p) { if (vP != NULL) { Place_vec_expand(vP, nP); vP->e[nP] = p; nP++; } return (visit != NULL ? visit(p) : FALSE); } } bool_t EnumElemsOfElem(Place_vec_t root, uint dimPiv, uint dimObj, VisitFunc_t visit, Place_vec_t *vP) { demand(dimPiv <= 3, "invalid dimension for pivot elements"); demand(dimObj <= 3, "invalid dimension for target elements"); demand(dimPiv != dimObj, "pivot and target dimensions must be distinct"); /* Set {stp[0..1]} to generators of all the even walks that do not change {p.elt[dim]}. */ StepFunc_t stp[3]; switch(dimPiv) { case 0: /* Pivot is node: */ switch(dimObj) { case 1: /* edges */ stp[0] = &Flip2; stp[1] = &Flip3; stp[2] = &Flip1; break; case 2: /* walls */ stp[0] = &Flip1; stp[1] = &Flip3; stp[2] = &Flip2; break; case 3: /* cells */ stp[0] = &Flip1; stp[1] = &Flip2; stp[2] = &Flip3; break; default: assert(FALSE); } break; case 1: /* Pivot is edge: */ switch(dimObj) { case 0: /* nodes */ stp[0] = &Flip2; stp[1] = &Flip3; stp[2] = &Flip0; break; case 2: /* walls */ stp[0] = &Flip0; stp[1] = &Flip3; stp[2] = &Flip2; break; case 3: /* cells */ stp[0] = &Flip0; stp[1] = &Flip2; stp[2] = &Flip3; break; default: assert(FALSE); } break; case 2: /* Pivot is wall: */ switch(dimObj) { case 0: /* nodes */ stp[0] = &Flip3; stp[1] = &Flip1; stp[2] = &Flip0; break; case 1: /* edges */ stp[0] = &Flip3; stp[1] = &Flip0; stp[2] = &Flip1; break; case 3: /* cells */ stp[0] = &Flip1; stp[1] = &Flip0; stp[2] = &Flip3; break; default: assert(FALSE); } break; case 3: /* Pivot is cell: */ switch(dimObj) { case 0: /* nodes */ stp[0] = &Flip2; stp[1] = &Flip1; stp[2] = &Flip0; break; case 1: /* edges */ stp[0] = &Flip2; stp[1] = &Flip0; stp[2] = &Flip1; break; case 2: /* walls */ stp[0] = &Flip1; stp[1] = &Flip0; stp[2] = &Flip2; break; default: assert(FALSE); } break; default: assert(FALSE); } /* We should visit {p} only after a {stp[2]} or a new root: */ auto bool_t MyVisit(Place_t p); /* Appends {p} to {vP} and calls {visitNode(p)}. */ VisitFunc_t vis[3]; vis[0] = NULL; vis[1] = &MyVisit; vis[2] = &MyVisit; int nP = 0; /* Visited places are {vP->e[0..nP-1]}, if {vP != NULL}. */ bool_t stop = EnumOrbits(root, 2, stp, vis, vP); /* Trim the visit list to the true size: */ if (vP != NULL) { Place_vec_trim(vP, nP); } /* Return the abort indicator: */ return stop; bool_t MyVisit(Place_t p) { if (vP != NULL) { Place_vec_expand(vP, nP); vP->e[nP] = p; nP++; } return (visit != NULL ? visit(p) : FALSE); } } bool_t EnumIncidencesOfElem(Place_vec_t root, uint dimPiv, uint dimObj, VisitFunc_t visit, Place_vec_t *vP) { demand(dimPiv <= 3, "invalid dimension for pivot elements"); demand(dimObj <= 3, "invalid dimension for target elements"); demand(dimPiv != dimObj, "pivot and target dimensions must be distinct"); /* Get two {stp}s that geneerate all even walks that do not change {p.elt[dimPiv]}. The function {stp[0]} should also preserve {p.elt[dimObj]}. */ StepFunc_t stp[2]; switch(dimPiv) { case 0: /* Pivot is node: */ switch(dimObj) { case 1: /* edges */ stp[0] = &Flip23; stp[1] = &Flip13; break; case 2: /* walls */ stp[0] = &Flip13; stp[1] = &Flip23; break; case 3: /* cells */ stp[0] = &Flip12; stp[1] = &Flip32; break; default: assert(FALSE); } break; case 1: /* Pivot is edge: */ switch(dimObj) { case 0: /* nodes */ stp[0] = &Flip23; stp[1] = &Flip03; break; case 2: /* walls */ stp[0] = &Flip30; stp[1] = &Flip32; break; case 3: /* cells */ stp[0] = &Flip02; stp[1] = &Flip32; break; default: assert(FALSE); } break; case 2: /* Pivot is wall: */ switch(dimObj) { case 0: /* nodes */ stp[0] = &Flip13; stp[1] = &Flip10; break; case 1: /* edges */ stp[0] = &Flip30; stp[1] = &Flip10; break; case 3: /* cells */ stp[0] = &Flip01; stp[1] = &Flip03; break; default: assert(FALSE); } break; case 3: /* Pivot is cell: */ switch(dimObj) { case 0: /* nodes */ stp[0] = &Flip12; stp[1] = &Flip10; break; case 1: /* edges */ stp[0] = &Flip02; stp[1] = &Flip01; break; case 2: /* walls */ stp[0] = &Flip01; stp[1] = &Flip02; break; default: assert(FALSE); } break; default: assert(FALSE); } /* We should visit {p} only after a {stp[2]} or a new root: */ auto bool_t MyVisit(Place_t p); /* Appends {p} to {vP} and calls {visitNode(p)}. */ VisitFunc_t vis[3]; vis[0] = NULL; vis[1] = MyVisit; vis[2] = MyVisit; int nP = 0; /* Visited places are {vP->e[0..nP-1]}, if {vP != NULL}. */ /* OK, now enumerate the orbits: */ bool_t stop = EnumOrbits(root, 2, stp, vis, NULL); /* Trim the visit list to the true size: */ if (vP != NULL) { Place_vec_trim(vP, nP); } /* Return the abort indicator: */ return stop; bool_t MyVisit(Place_t p) { if (vP != NULL) { Place_vec_expand(vP, nP); vP->e[nP] = p; nP++; } return (visit != NULL ? visit(p) : FALSE); } } #define OctfEnum_C_author \ "Various Modula-3 enumeration procedures for 3D maps were written 1998" \ "by Luis Arturo Perez Lozada, UNICAMP, inspired on the " \ "similar quad-edge tools that had been implemented in Modula-3 by " \ "J.Stolfi and R.M.Rosi (ca. 1994).\n" \ "\n" \ "The 3D map enumeration procedures were entirely rewritten in\n" \ "jan/2007 by J.Stolfi, as special cases of a general\n" \ "{EnumOrbits} procedure. The latter was conceived in 1993,\n" \ "for the textbook /Fundamentos de Geometria Computacional/\n" \ "written by P.J.Rezende and J.Stolfi for the Escola de Programaçăo." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/OctfRep.c /* See {OctfRep.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-28 04:14:33 by stolfi */ // #INCLUDE // #INCLUDE #include #include #include #include #include #define OctfRep_C_copyright \ "Copyright © 1998, 2007 Universidade Estadual de Campinas (UNICAMP)" // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Map.c /* See {Map.h} */ // #INCLUDE /* 3D map operations pecialized for triangulations -- maps with tetrahedral cells.*/ // #TIMESTAMP /* Last edited on 2007-01-31 14:14:42 by stolfi */ #define Map_C_COPYRIGHT \ "Copyright © 2000 by the State University of Campinas (UNICAMP)" // #INCLUDE // #INCLUDE ElemTableRec_t MakeElemTable(Place_vec_t root) { ElemTableRec_t top; top.wedge = EnumWedges(root, NULL); top.node = Place_vec_new(0); (void)EnumElems(root, 0, NULL, &top.node); top.edge = Place_vec_new(0); (void)EnumElems(root, 1, NULL, &top.edge); top.wall = Place_vec_new(0); (void)EnumElems(root, 2, NULL, &top.wall); top.cell = Place_vec_new(0); (void)EnumElems(root, 3, NULL, &top.cell); uint m = digits(top.wedge.ne) + 1; fprintf(stderr, "\n"); fprintf(stderr, "nodes = %*d\n", m, top.node.ne); fprintf(stderr, "edges = %*d\n", m, top.edge.ne); fprintf(stderr, "walls = %*d\n", m, top.wall.ne); fprintf(stderr, "cells = %*d\n", m, top.cell.ne); fprintf(stderr, "\n"); fprintf(stderr, "wedges = %*d\n", m, top.wedge.ne); fprintf(stderr, "\n"); /* Euler's Number */ int euler = top.node.ne - top.edge.ne + top.wall.ne - top.cell.ne; fprintf(stderr,"Euler's number = %d\n", euler); return top; } #define Map_C_author \ "Created 2000 by L. A. P. Lozada, based on 1996 procedures by\n" \ " R. M. Rosi and J. Stolfi.\n" \ "Revisions:\n" \ " 2007-01-26 : Converted to C by J.Stolfi.\n" \ " 2007-01-31 : Moved from {Triangulation.c} to here the\n" \ " procedure {MakeElemTable} and related ones." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Triangulation.c /* See {Triangulation.h} */ // #INCLUDE /* 3D map operations pecialized for triangulations -- maps with tetrahedral cells.*/ // #TIMESTAMP /* Last edited on 2007-01-31 14:12:53 by stolfi */ #define Triangulation_C_COPYRIGHT \ "Copyright © 2000 by the State University of Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include #include #include #include Node_t MakeNode(void) { return (Node_t)notnull(malloc(sizeof(NodeRec_t)), "no mem"); } Cell_t MakeCell(void) { return (Cell_t)notnull(malloc(sizeof(CellRec_t)), "no mem"); } NodeOrCell_t Org(Place_t p) { return PWedge(p)->org[SrotBits(p)]; } NodeOrCell_t Pneg(Place_t p) { p = Srot(p); return PWedge(p)->org[SrotBits(p)]; } NodeOrCell_t Ppos(Place_t p) { p = Tors(p); return PWedge(p)->org[SrotBits(p)]; } void SetOrg(Place_t p, Node_t n) { assert(DualBit(p) == 0); /* [!!! Added by JS. If {p} is dual, should use SetPneg instead. !!!] */ PWedge(p)->org[SrotBits(p)] = (NodeOrCell_t)n; } void SetPneg(Place_t p, Cell_t n) { assert(DualBit(p) == 1); /* [!!! Added by JS. If {p} is dual, should use SetOrg instead. !!!] */ p = Srot(p); PWedge(p)->org[SrotBits(p)] = (NodeOrCell_t)n; } void SetPpos(Place_t p, Cell_t n) { assert(DualBit(p) == 1); /* [!!! Added by JS. If {p} is dual, should use SetDes instead. !!!] */ p = Tors(p); PWedge(p)->org[SrotBits(p)] = (NodeOrCell_t)n; } void SetOrgAll(Place_t p, Node_t n) { assert(DualBit(p) == 0); /* [!!! Added by JS. If {p} is dual, should use SetPneg instead. !!!] */ Place_vec_t pv = (Place_vec_t){/*ne*/ 1, /*e*/ &p}; Place_vec_t nei = RenumberEdgesOutOfNodes(&pv); int i; for(i = 0; i < nei.ne; i++) { Place_t b = nei.e[i]; Place_t c = b; do { SetOrg(c,n); c = NextF(c); } while (c != b); } } void SetPnegOfWall(Place_t p, Cell_t n) { assert(DualBit(p) == 1); /* [!!! Added by JS. If {p} is dual, should use SetOrg instead. !!!] */ Place_t t = p; do { SetPneg(t, n); t = PrevE(t); } while (t != p); } void SetPnegOfNearbyWalls(Place_t p, Cell_t n) { assert(DualBit(p) == 1); /* [!!! Added by JS. If {p} is dual, should use SetOrg instead. !!!] */ SetPnegOfWall(p,n); Place_t t = p; do { SetPnegOfWall(Clock(PrevF(t)),n); t = PrevE(t); } while (t != p); } void SetPposOfWall(Place_t p, Cell_t n) { assert(DualBit(p) == 1); /* [!!! Added by JS. If {p} is dual, should use SetDes instead. !!!] */ Place_t t = p; do { SetPpos(t, n); t = PrevE(t); } while (t != p); } void SetPposQUX(Place_t p, Cell_t n) { assert(DualBit(p) == 1); /* [!!! Added by JS. If {p} is dual, should use SetDes instead. !!!] */ Place_t t = Clock(p); SetPnegOfNearbyWalls(t,n); do { SetPnegOfNearbyWalls(PrevF(t),n); t = PrevE(t); } while (t != Clock(p)); } Node_t OrgV(Place_t p) { return (Node_t)(Org(p)); } Node_t DesV(Place_t p) { return OrgV(Clock(p)); } Cell_t PnegP(Place_t p) { return (Cell_t)(Pneg(p)); } Cell_t PposP(Place_t p) { return PnegP(Clock(p)); } FourNodes_t TetraNegNodes(Place_t p) { /* Valid for the versions Spin(p), Clock(p) and SpinClock(p). */ assert(Pneg(p) != NULL); Node_t n0 = OrgV(p); Node_t n1 = OrgV(NextE(p)); Node_t n2 = OrgV(PrevE(p)); Node_t n3 = OrgV(PrevE(PrevF(p))); assert(Pneg(p) == Ppos(PrevE(PrevF(p)))); assert((n0 != n1) && (n0 != n2) && (n0 != n3) && (n1 != n2) && (n1 != n3) && (n2 != n3)); return (FourNodes_t){{n0,n1,n2,n3}}; } FourNodes_t TetraPosNodes(Place_t p) { /* Valid for the versions Spin(p), Clock(p) and SpinClock(p). */ /* [!!! Should be just TetraNegNodes(q) where {q = Spin(p)} or {q = Clock(p)} ? !!!] */ assert(Ppos(p)!=NULL); Node_t n0 = OrgV(p); Node_t n1 = OrgV(NextE(p)); Node_t n2 = OrgV(PrevE(p)); Node_t n3 = OrgV(PrevE(NextF(p))); assert(Ppos(p) == Pneg(PrevE(NextF(p)))); return (FourNodes_t){{n0,n1,n2,n3}}; } FourWalls_t TetraWalls(Place_t p) { assert(Pneg(p)!=NULL); Wall_t f0 = PWall(p); Wall_t f1 = PWall(PrevF(p)); Wall_t f2 = PWall(PrevF(NextE(p))); Wall_t f3 = PWall(PrevF(PrevE(p))); assert((f0 != f1) && (f0 != f2) && (f0 != f3) && (f1 != f2) && (f1 != f3) && (f2 != f3)); return (FourWalls_t){{f0,f1,f2,f3}}; } SixEdges_t TetraEdges(Place_t p) { assert(Pneg(p)!=NULL); Edge_t e0 = PEdge(p); Edge_t e1 = PEdge(NextE(p)); Edge_t e2 = PEdge(PrevE(p)); Edge_t e3 = PEdge(NextE(PrevF(p))); Edge_t e4 = PEdge(PrevE(PrevF(p))); Edge_t e5 = PEdge(NextE(PrevF(NextE(p)))); assert((e0 != e1) && (e0 != e2) && (e0 != e3) && (e0 != e4) && (e0 != e5)); assert((e1 != e2) && (e1 != e3) && (e1 != e4) && (e1 != e5)); assert((e2 != e3) && (e2 != e4) && (e2 != e5)); assert((e3 != e4) && (e3 != e5)); assert(e4 != e5); return (SixEdges_t){{e0,e1,e2,e3,e4,e5}}; } ThreeEdges_t TriangEdges(Place_t p) { Edge_t e0 = PEdge(p); Edge_t e1 = PEdge(NextE(p)); Edge_t e2 = PEdge(PrevE(p)); assert((e0 != e1) && (e0 != e2) && (e1 != e2)); return (ThreeEdges_t){{e0,e1,e2}}; } bool_t EdgeIsBorder(Place_t p) { Place_t b = p; do { if ((Pneg(b) == NULL)){ return TRUE; } b = NextF(b); } while (b != p); return FALSE; } bool_t WallIsBorder(Place_t p) { return ((Ppos(p) == NULL) || (Pneg(p) == NULL)); } FiveNodes_t TetraNegPosNodes(Place_t p) { /* Valid for the versions Spin(p), Clock(p) and SpinClock(p). */ /* Used {Org} instead of {OrgV} so it could be used in the dual map. However the assertion is valid only if {p} is on the primal map. */ Node_t n0 = OrgV(p); Node_t n1 = OrgV(NextE(p)); Node_t n2 = OrgV(PrevE(p)); Node_t n3 = OrgV(PrevE(PrevF(p))); Node_t n4 = OrgV(PrevE(NextF(p))); assert(Ppos(p) == Pneg(PrevE(NextF(p))) && (Pneg(p) == Ppos(PrevE(PrevF(p))))); return (FiveNodes_t){{n0,n1,n2,n3,n4}}; } EightPlaces_t MakeTetraTopo(uint nx, uint ny) { uint wedgeCount = 0; uint cellCount = 0; auto Place_t MakeTriangle(void); /* Creates a new `naked' triangular wall. The resulting structure has three wedges connected by {NextE} links, sharing the same {Wall_t}, without any {Cell_t}s. */ Place_t MakeTriangle(void) { Place_t a = MakeWedge(); Place_t b = MakeWedge(); Place_t c = MakeWedge(); Wall_t f = PWall(a); Node_t u = MakeNode(); Node_t v = MakeNode(); Node_t w = MakeNode(); PWedge(a)->num = wedgeCount; wedgeCount++; SetOrg(a, u); SetOrg(Clock(a),v); PWedge(b)->num = wedgeCount; wedgeCount++; SetNextE(a,b); SetWallInfo(b,f); SetOrg(b,v); SetOrg(Clock(b),w); PWedge(c)->num = wedgeCount; wedgeCount++; SetNextE(b,c); SetWallInfo(c,f); SetOrg(c, w); SetOrg(Clock(c), OrgV(a)); return a; } auto Place_t AddTwoTriangles(Place_t a); /* Builds an incomplete tetrahedral cell by adding two additional triangular walls to an exisiting `naked' wall. The argument {a} is a place on the existing wall, as returned by MakeTriangle(). The procedure returns a place {f} on one of the new triangles. */ Place_t AddTwoTriangles(Place_t a) { Place_t c = NextE(NextF(a)); SetEdgeInfo(a, PEdge(PrevE(c))); Place_t f = MakeTriangle(); Place_t g = MakeTriangle(); SetNextF(PrevE(a), PrevE(f)); SetEdgeInfo(PrevE(f), PEdge(PrevE(a))); SetOrgAll(PrevE(a), OrgV(PrevE(a))); SetOrgAll(Clock(PrevE(a)), OrgV(Clock(PrevE(a)))); SetNextF(Clock(f), NextE(c)); SetEdgeInfo(Clock(f), PEdge(NextE(c))); SetOrgAll(NextE(c), OrgV(NextE(c))); SetOrgAll(Clock(NextE(c)), OrgV(Clock(NextE(c)))); SetNextF(NextE(g), NextE(f)); SetEdgeInfo(NextE(g), PEdge(NextE(f))); SetOrgAll(NextE(f), OrgV(NextE(f))); SetOrgAll(Clock(NextE(f)), OrgV(Clock(NextE(f)))); SetNextF(g, c); SetEdgeInfo(g, PEdge(c)); SetOrgAll(c, OrgV(c)); SetOrgAll(Clock(c), OrgV(Clock(c))); SetNextF(PrevE(g), Clock(NextE(a))); SetEdgeInfo(PrevE(g), PEdge(Clock(NextE(a)))); SetOrgAll(NextE(a), OrgV(NextE(a))); SetOrgAll(Clock(NextE(a)), OrgV(Clock(NextE(a)))); Cell_t p = MakeCell(); p->num = cellCount; cellCount++; SetPnegOfNearbyWalls(f,p); return f; } auto Place_t FinishCellRow(Place_t a); /* Adds one new row of tetradedral cells to a started row, and returns a place on the last cell. */ Place_t FinishCellRow(Place_t a) { int col; for (col = 0; col < nx; col++) { a = AddTwoTriangles(a); } return a; } Place_t t = NULL, b = NULL; EightPlaces_t ca = (EightPlaces_t){{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}; /* Create bottom row of triangles: */ int col; for (col = 0; col < nx; col++) { Place_t c = MakeTriangle(); if (col == 0) { t = c; } else { SpliceWalls(NextE(b), Clock(PrevE(c))); SetEdgeInfo(NextE(b), PEdge(Clock(PrevE(c)))); SetOrgAll(NextE(b), OrgV(NextE(b))); SetOrgAll(Clock(NextE(b)), OrgV(Clock(NextE(b)))); b = c; } } ca.p[2] = t; ca.p[7] = Spin(Clock(b)); /* Add {ny} rows of cells: */ int row; for (row = 0; row < ny; row++) { /* First triangle of row: */ Place_t a = MakeTriangle(); if (row == 0){ ca.p[1] = Clock(PrevE(a)); } if (row == ny-1){ ca.p[4] = Spin(PrevE(a)); } SpliceWalls(Clock(a), Clock(PrevE(t))); SetOrgAll(PrevE(t), OrgV(PrevE(t))); SetOrgAll(Clock(PrevE(t)), OrgV(Clock(PrevE(t)))); /* Add {nx} cells to row: */ Place_t aa = FinishCellRow(a); t = PrevF(t); SetOrg(PrevE(t), OrgV(PrevE(a))); b = PrevF(b); SetOrg(Clock(NextE(b)), OrgV(PrevE(aa))); if (row == 0){ ca.p[0] = Clock(Spin(PrevE(aa))); } if ((row == ny-1)){ ca.p[5] = PrevE(aa); } } ca.p[3] = Spin(t); ca.p[6] = Clock(b); return ca; } void EmphasizeTetrahedron(Place_t a, Place_t b, uint n) { auto void HideNode(Node_t v); /* Hide the node {v}. */ void HideNode(Node_t v) { v->exists = FALSE; } auto void HideEdge(Place_t a); /* Hide the edge {PEdge(a)}.*/ void HideEdge(Place_t a) { PEdge(a)->exists = FALSE; } auto void HideWall(Place_t a); /* Hide the wall {PWall(a)}.*/ void HideWall(Place_t a) { PWall(a)->exists = FALSE; } auto void HideWallsOfEdge(Place_t a); /* Hide all the walls incident to the edge {PEdge(a)}. [!!! Actually hides the {n-1} walls that come before {PWall(a)} around {Pedge(a)}. !!!] */ void HideWallsOfEdge(Place_t a) { Place_t an = PrevF(a); int j; for (j = 1; j < n; j++) { HideWall(an); an = PrevF(an); } } /* Collects certain {n} places {ta[0..n-1],tb[0..n-1]}: [???] */ Place_t ta[101], tb[101]; ta[0] = a; tb[0] = b; int i; for (i = 1; i < n; i++) { ta[i] = Clock(PrevE(NextF(NextE(ta[i-1])))); tb[i] = Clock(PrevE(NextF(NextE(tb[i-1])))); } /* Hide {n-1} walls incident to the edges of those places: [???] */ for (i = 0; i < n; i++) { HideWallsOfEdge(ta[i]); HideWallsOfEdge(tb[i]); } /* Hide the origin nodes of those places: [???] */ for (i = 1; i < n; i++) { HideNode(OrgV(tb[i])); HideNode(OrgV(ta[i])); Place_t dn = tb[i]; int j; for (j = 0; j <= n /* [!!! Should it be {j < n}? !!!] */; j++) { HideEdge(PrevE(dn)); dn = PrevF(dn); } } /* Hide certain edges related to those places: [???] */ for (i = 0; i < (n-1); i++) { HideEdge(NextE(ta[i])); HideEdge(NextE(NextF(ta[i]))); } } Place_t Glue(Place_t a, Place_t b, uint n, bool_t setorg) { /* fprintf(stderr, "colou\n"); */ assert(n >= 1); /* sanity check */ /* Collect interesting places {ta[0..n-1], tb[0..n-1]}: */ Place_t ta[101], tb[101]; int i; ta[0] = a; tb[0] = b; if (n > 1) { for (i = 1; i < n; i++) { ta[i] = Clock(PrevE(PrevF(NextE(ta[i-1])))); assert(ta[i]!=a); tb[i] = Clock(PrevE(NextF(NextE(tb[i-1])))); assert(tb[i]!=b); } } Meld(b, a); /* Update the edge slots for {i == 0}: */ SetRingEdgeInfo(a, PEdge(a)); SetRingEdgeInfo(NextE(a), PEdge(NextE(a))); SetRingEdgeInfo(PrevE(a), PEdge(PrevE(a))); if (setorg) { /* Update the node slots for {i == 0}: */ SetOrgAll(a, OrgV(a)); SetOrgAll(Clock(a), OrgV(Clock(a))); SetOrgAll(NextE(a), OrgV(NextE(a))); SetOrgAll(Clock(NextE(a)), OrgV(Clock(NextE(a)))); SetOrgAll(PrevE(a), OrgV(PrevE(a))); SetOrgAll(Clock(PrevE(a)), OrgV(Clock(PrevE(a)))); } /* Update the cell slots for {i == 0}: */ SetPneg(a, PnegP(b)); SetPneg(PrevE(a), PnegP(PrevE(b))); SetPneg(NextE(a), PnegP(NextE(b))); for (i = 1; i < n; i++) { Meld(tb[i],ta[i]); /* Update the edge slots for {i > 0}: */ SetRingEdgeInfo(ta[i], PEdge(ta[i])); SetRingEdgeInfo(NextE(ta[i]), PEdge(NextE(ta[i]))); SetRingEdgeInfo(PrevE(ta[i]), PEdge(PrevE(ta[i]))); if (setorg) { /* Update the node slots for {i > 0}: */ SetOrgAll(ta[i], OrgV(ta[i])); SetOrgAll(Clock(ta[i]), OrgV(Clock(ta[i]))); SetOrgAll(NextE(ta[i]), OrgV(NextE(ta[i]))); SetOrgAll(Clock(NextE(ta[i])), OrgV(Clock(NextE(ta[i])))); SetOrgAll(PrevE(ta[i]), OrgV(PrevE(ta[i]))); SetOrgAll(Clock(PrevE(ta[i])), OrgV(Clock(PrevE(ta[i])))); } /* Update the cell slots for {i > 0}: */ Cell_t f = PnegP(tb[i]); Cell_t g = PnegP(PrevE(tb[i])); Cell_t h = PnegP(NextE(tb[i])); SetPneg(ta[i], f); SetPneg(PrevE(ta[i]), g); SetPneg(NextE(ta[i]), h); } if (setorg) { SetOrgAll(Clock(PrevE(PrevF(PrevE(ta[n-1])))),OrgV(PrevE(a))); } return ta[n-1]; } #define Triangulation_C_author \ "Created 2000 by L. A. P. Lozada, based on 1996 procedures by\n" \ " R. M. Rosi and J. Stolfi.\n" \ "Revisions:\n" \ " 03-08-2000 : Optimized version of the Read and Write procedures by J. Stolfi.\n" \ " 30-08-2000 : Modified the Read and Write procedures for include the case\n" \ " when the cells are octahedra.\n" \ " 07-10-2000 : Added procedure for compute the barycenter of a tetrahedron.\n" \ " 27-01-2001 : Modified for exploding cubic cells." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/PZGeo3.c /* See {PZGeo3.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-25 10:11:33 by stolfi */ #define PZGeo3_C_author \ "Created by J. Stolfi and H. C. G. Leităo in 1999.\n" \ "Adapted by L. A. P. Lozada, 1999-2000." #include #include #include r3_t PZGeo3_LinearInterpolate(double t, double a, r3_t *pa, double b, r3_t *pb) { double Ca, Cb; if ((b - a) != 0.0) { Ca = (b - t)/(b - a); Cb = 1 - Ca; } else { Ca = 0.5; Cb = 0.5; } return (r3_t) {{ Ca*pa->c[0] + Cb*pb->c[0], Ca*pa->c[1] + Cb*pb->c[1], Ca*pa->c[2] + Cb*pb->c[2] }}; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/PZGeo4.c /* See {PZGeo4.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-25 10:22:12 by stolfi */ #define PZGeo4_C_author \ "Modified by L.A.P.Lozada on 2000-03-03." #include #include r4_t PZGeo4_LinearInterpolate(double t, double a, r4_t *pa, double b, r4_t *pb) { double Ca, Cb; if ((b - a) != 0.0) { Ca = (b - t)/(b - a); Cb = 1 - Ca; } else { Ca = 0.5; Cb = 0.5; } return (r4_t){{ Ca*pa->c[0] + Cb*pb->c[0], Ca*pa->c[1] + Cb*pb->c[1], Ca*pa->c[2] + Cb*pb->c[2], Ca*pa->c[3] + Cb*pb->c[3] }}; } void PZGeo4_HermiteInterpolate ( double t, double a, r4_t *pa, r4_t *va, double b, r4_t *pb, r4_t *vb, r4_t *p, r4_t *v ) { assert(a <= b); /* If the interval has zero width, return the mean of the positions (which is an OK result) and the mean of the velocities (which is almost certainly wrong). */ if (b - a == 0.0) { /* Interval is degenerate: */ r4_mix(0.5, pa, 0.5, pb, p); r4_mix(0.5, va, 0.5, vb, v); } else { double tab = b - a; double tax = t - a; double txb = b - t; double rax = tax/tab; double rxb = txb/tab; double Cpa = rxb * rxb * (3.0 * rax + rxb); double Dpa = - 6.0 * rax * rxb / tab; double Cva = + rax * rxb * txb; double Dva = + rxb * (rxb - 2.0 * rax); double Cvb = - rax * rxb * tax; double Dvb = + rax * (rax - 2.0 * rxb); double Cpb = rax * rax * (rax + 3.0 * rxb); double Dpb = + 6.0 * rax * rxb / tab; (*p) = (r4_t){{ Cpa*pa->c[0] + Cva*va->c[0] + Cvb*vb->c[0] + Cpb*pb->c[0], Cpa*pa->c[1] + Cva*va->c[1] + Cvb*vb->c[1] + Cpb*pb->c[1], Cpa*pa->c[2] + Cva*va->c[2] + Cvb*vb->c[2] + Cpb*pb->c[2], Cpa*pa->c[3] + Cva*va->c[3] + Cvb*vb->c[3] + Cpb*pb->c[3] }}; (*v) = (r4_t){{ Dpa*pa->c[0] + Dva*va->c[0] + Dvb*vb->c[0] + Dpb*pb->c[0], Dpa*pa->c[1] + Dva*va->c[1] + Dvb*vb->c[1] + Dpb*pb->c[1], Dpa*pa->c[2] + Dva*va->c[2] + Dvb*vb->c[2] + Dpb*pb->c[2], Dpa*pa->c[3] + Dva*va->c[3] + Dvb*vb->c[3] + Dpb*pb->c[3] }}; } } r4_t PZGeo4_BSplineApproximation ( double t, double a, double b, r4_t *Pabc, double c, r4_t *Pbcd, double d, r4_t *Pcde, double e, r4_t *Pdef, double f ) { r4_t Ptbc = PZGeo4_LinearInterpolate(t, a, Pabc, d, Pbcd); r4_t Ptcd = PZGeo4_LinearInterpolate(t, b, Pbcd, e, Pcde); r4_t Ptde = PZGeo4_LinearInterpolate(t, c, Pcde, f, Pdef); r4_t Pttc = PZGeo4_LinearInterpolate(t, b, &Ptbc, d, &Ptcd); r4_t Pttd = PZGeo4_LinearInterpolate(t, c, &Ptcd, e, &Ptde); r4_t Pttt = PZGeo4_LinearInterpolate(t, c, &Pttc, d, &Pttd); return Pttt; } r4_t PZGeo4_CubicBezier ( double t, r4_t *Pabc, r4_t *Pbcd, r4_t *Pcde, r4_t *Pdef ) { r4_t Ptbc = PZGeo4_LinearInterpolate(t, 1.0, Pabc, 1.0, Pbcd); r4_t Ptcd = PZGeo4_LinearInterpolate(t, 1.0, Pbcd, 1.0, Pcde); r4_t Ptde = PZGeo4_LinearInterpolate(t, 1.0, Pcde, 1.0, Pdef); r4_t Pttc = PZGeo4_LinearInterpolate(t, 1.0, &Ptbc, 1.0, &Ptcd); r4_t Pttd = PZGeo4_LinearInterpolate(t, 1.0, &Ptcd, 1.0, &Ptde); r4_t Pttt = PZGeo4_LinearInterpolate(t, 1.0, &Pttc, 1.0, &Pttd); return Pttt; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Mis.c /* See {Mis.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-28 01:11:43 by stolfi */ #define Mis_C_author \ "Modified by L.A.P.Lozada on 00-01-06." // #INCLUDE #include #include #include #include #include #include #include #include double ThrowDouble(Random_t *coins, double radius) { return radius*(2*drandom() - 1); } void WritePoint4D(FILE *wr, r4_t *c) { r4_gen_print(wr, c, "%24.16e", "(", " ", ")"); } void WritePoint3D(FILE *wr, r3_t *c) { r3_gen_print(wr, c, "%10.6f", "(", " ", ")"); } void WritePoint2D(FILE *wr, r2_t *c) { r2_gen_print(wr, c, "%10.6f", "(", " ", ")"); } void WriteIntensity(FILE *wr, float r) { fprintf(wr, "%5.3f", r); } void WriteColor(FILE *wr, frgb_t *c) { WriteIntensity(wr, c->c[0]); fprintf(wr, " "); WriteIntensity(wr, c->c[1]); fprintf(wr, " "); WriteIntensity(wr, c->c[2]); } /* END WriteColor */ void WriteRadius(FILE *wr, float r) { fprintf(wr, "%5.3f", r); } /* vec_typeimpl(uint_vec_t,uint_vec,uint); */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Pov.c /* See {Pov.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-25 10:41:22 by stolfi */ #include #include void WritePOVCoord(FILE *wr, double c) { fprintf(wr, "%10.6f", c); } void WritePOVPoint(FILE *wr, r3_t *p) { fprintf(wr, "<"); WritePOVCoord(wr, p->c[0]); fprintf(wr, ","); WritePOVCoord(wr, p->c[1]); fprintf(wr, ","); WritePOVCoord(wr, p->c[2]); fprintf(wr, ">"); } void WritePOVColor(FILE *wr, frgb_t *cr) { fprintf(wr, "rgb <"); fprintf(wr, "%10.4f", cr->c[0]); fprintf(wr, ","); fprintf(wr, "%10.4f", cr->c[1]); fprintf(wr, ","); fprintf(wr, "%10.4f", cr->c[2]); fprintf(wr, ">"); } void WritePOVColorTransp(FILE *wr, frgb_t *cr, float tr, bool_t filter) { if (filter){ fprintf(wr, "rgbf"); } else { fprintf(wr, "rgbt"); } fprintf(wr, " <"); fprintf(wr, "%10.4f", cr->c[0]); fprintf(wr, ","); fprintf(wr, "%10.4f", cr->c[1]); fprintf(wr, ","); fprintf(wr, "%10.4f", cr->c[2]); fprintf(wr, ","); fprintf(wr, "%10.4f", tr); fprintf(wr, ">"); } void WritePOVSphere ( FILE *wr, r3_t *p, float radius, frgb_t *cr, float tr, bool_t filter, char *tag1 /* DF "" */, char *tag2 /* DF "" */ ) { fprintf(wr, " sphere {\n"); fprintf(wr, " "); WritePOVPoint(wr,p); fprintf(wr, ", %.6f\n", radius); fprintf(wr, " texture { pigment { color "); WritePOVColorTransp(wr,cr,tr,filter); fprintf(wr, " } } // %s %s\n", tag1, tag2); fprintf(wr, " } \n"); fprintf(wr, "\n"); fflush(wr); } void WritePOVCylinder ( FILE *wr, r3_t *o, r3_t *d, float radius, frgb_t *cr, float tr, bool_t filter, char *tag1 /* DF "" */, char *tag2 /* DF "" */ ) { fprintf(wr, " cylinder {\n"); fprintf(wr, " "); WritePOVPoint(wr,o); fprintf(wr, ",\n"); fprintf(wr, " "); WritePOVPoint(wr,d); fprintf(wr, ",\n"); fprintf(wr, " %.6f\n", radius); fprintf(wr, " open\n"); fprintf(wr, " texture { pigment { color "); WritePOVColorTransp(wr, cr, tr,filter); fprintf(wr, " } } // %s %s\n", tag1, tag2); fprintf(wr, " }\n"); fprintf(wr, "\n"); fflush(wr); } void WritePOVTriangle ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, frgb_t *cr, float tr, bool_t filter, char *tag1 /* DF "" */, char *tag2 /* DF "" */ ) { fprintf(wr," triangle { \n"); fprintf(wr," "); WritePOVPoint(wr,a); fprintf(wr, ",\n"); fprintf(wr," "); WritePOVPoint(wr,b); fprintf(wr, ",\n"); fprintf(wr," "); WritePOVPoint(wr,c); fprintf(wr, "\n"); fprintf(wr, " texture { pigment { color "); WritePOVColorTransp(wr, cr, tr, filter); fprintf(wr, " } finish { ambient 0.1 diffuse 0.9 } } // %s %s\n", tag1, tag2); fprintf(wr," }\n"); fprintf(wr,"\n"); fflush(wr); } void WritePOVTriangleTex ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, char *texture ) { fprintf(wr," triangle { \n"); fprintf(wr," "); WritePOVPoint(wr,a); fprintf(wr, ",\n"); fprintf(wr," "); WritePOVPoint(wr,b); fprintf(wr, ",\n"); fprintf(wr," "); WritePOVPoint(wr,c); fprintf(wr, "\n"); fprintf(wr, " texture { %s }\n", texture); fprintf(wr, " } \n"); fprintf(wr, "\n"); fflush(wr); } void WritePOVSquare ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, r3_t *d, frgb_t *cr, float tr, bool_t filter ) { fprintf(wr," union{\n"); fprintf(wr," "); fprintf(wr,"triangle {"); WritePOVPoint(wr,a); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,b); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,c); fprintf(wr,"}\n"); fprintf(wr," "); fprintf(wr,"triangle {"); WritePOVPoint(wr,c); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,d); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,a); fprintf(wr,"}\n"); fprintf(wr,"texture {\n"); fprintf(wr," pigment { color "); WritePOVColorTransp(wr,cr,tr,filter); fprintf(wr, " } finish { ambient 0.1 diffuse 0.9 } }\n"); fprintf(wr, " } \n"); fprintf(wr, "\n"); } void WritePOVTetrahedron ( FILE *wr, r3_t *u, r3_t *v, r3_t *w, r3_t *x, double du, double dv, double dw, double dx, frgb_t *cr, float tr, bool_t filter ) { fprintf(wr," intersection{\n"); fprintf(wr," plane{"); WritePOVPoint(wr,u); fprintf(wr,", "); WritePOVCoord(wr,du); fprintf(wr," }\n"); fprintf(wr," plane{"); WritePOVPoint(wr,v); fprintf(wr,", "); WritePOVCoord(wr,dv); fprintf(wr," }\n"); fprintf(wr," plane{"); WritePOVPoint(wr,w); fprintf(wr,", "); WritePOVCoord(wr,dw); fprintf(wr," }\n"); fprintf(wr," plane{"); WritePOVPoint(wr,x); fprintf(wr,", "); WritePOVCoord(wr,dx); fprintf(wr," }\n"); fprintf(wr," pigment { color rgbt <1.0000,1.0000,1.0000,0.925> }\n"); fprintf(wr," interior{\n"); fprintf(wr," media { emission "); WritePOVColorTransp(wr,cr,tr,filter); fprintf(wr," }\n"); fprintf(wr," }\n"); fprintf(wr," hollow\n"); fprintf(wr," }\n\n"); } void WritePOVSmoothTriangle ( FILE *wr, r3_t *a, r3_t *an, r3_t *b, r3_t *bn, r3_t *c, r3_t *cn, frgb_t *cr, float tr, bool_t filter ) { fprintf(wr, " smooth_triangle {\n"); fprintf(wr, " "); WritePOVPoint(wr,a); fprintf(wr, ", "); WritePOVPoint(wr,an); fprintf(wr, ",\n"); fprintf(wr, " "); WritePOVPoint(wr,b); fprintf(wr, ", "); WritePOVPoint(wr,bn); fprintf(wr, ",\n"); fprintf(wr, " "); WritePOVPoint(wr,c); fprintf(wr, ", "); WritePOVPoint(wr,cn); fprintf(wr, "\n"); /*fprintf(wr, " texture { wallexture } \n");*/ fprintf(wr, " pigment { color "); WritePOVColorTransp(wr,cr,tr,filter); fprintf(wr, " }\n"); fprintf(wr, " } \n"); fprintf(wr, "\n"); fflush(wr); } void WritePOVPenta ( FILE *wr, r3_t *a, r3_t *b, r3_t *c, r3_t *d, r3_t *e, frgb_t *cr, float tr, bool_t filter ) { fprintf(wr," union{\n"); fprintf(wr," ");fprintf(wr,"triangle {"); WritePOVPoint(wr,a); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,b); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,c); fprintf(wr,"}\n"); fprintf(wr," ");fprintf(wr,"triangle {"); WritePOVPoint(wr,c); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,d); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,a); fprintf(wr,"}\n"); fprintf(wr," ");fprintf(wr,"triangle {"); WritePOVPoint(wr,d); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,e); fprintf(wr,",\n"); fprintf(wr," ");WritePOVPoint(wr,a); fprintf(wr,"}\n"); fprintf(wr," pigment { color "); WritePOVColorTransp(wr,cr,tr,filter); fprintf(wr, " }\n"); fprintf(wr, " } \n"); fprintf(wr, "\n"); } #define Pov_C_author \ "Modified by L.A.P.Lozada on 00-05-17." #define Pov_C_COPYRIGHT \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/BigCube.c /* See {BigCube.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:44:08 by stolfi */ #define BigCube_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include Place_t GlueBigCube(Place_t a, Place_t b, uint n); Place_t GlueBigCube(Place_t a, Place_t b, uint n) { demand(n >= 1, "order must be at least 1"); int M = 20; Place_t ta[M*M]; Place_t tb[M*M]; ta[0*M + 0] = a; tb[0*M + 0] = b; int i, j; for (i = 1; i < n; i++) { ta[i*M + 0] = Clock(PrevF(NextE(NextE(ta[(i-1)*M+0])))); tb[i*M + 0] = Clock(NextF(NextE(NextE(tb[(i-1)*M+0])))); } for (i = 0; i < n; i++) { for (j = 1; j < n; j++) { ta[i*M + j] = Clock(PrevE(PrevF(NextE(ta[i*M + (j-1)])))); tb[i*M + j] = Clock(PrevE(NextF(NextE(tb[i*M + (j-1)])))); assert(ta[i*M + j]!=a); assert(tb[i*M + j]!=b); } } for (i = 0; i < n; i++) { Meld(tb[i*M + 0], ta[i*M + 0]); /* Update the edge slots */ SetRingEdgeInfo(ta[i*M + 0], PWedge(ta[i*M + 0])->edge); SetRingEdgeInfo(NextE(ta[i*M + 0]), PWedge(NextE(ta[i*M + 0]))->edge); SetRingEdgeInfo(NextE(NextE(ta[i*M + 0])), PWedge(NextE(NextE(ta[i*M + 0])))->edge); SetRingEdgeInfo(NextE(NextE(NextE(ta[i*M + 0]))), PWedge(NextE(NextE(NextE(ta[i*M + 0]))))->edge); /* Update the node slots */ SetOrgAll(ta[i*M + 0], OrgV(ta[i*M + 0])); SetOrgAll(NextE(ta[i*M + 0]), OrgV(NextE(ta[i*M + 0]))); SetOrgAll(NextE(NextE(ta[i*M + 0])), OrgV(NextE(NextE(ta[i*M + 0])))); SetOrgAll(NextE(NextE(NextE(ta[i*M + 0]))), OrgV(NextE(NextE(NextE(ta[i*M + 0]))))); SetOrgAll(Clock(ta[i*M + 0]), OrgV(Clock(ta[i*M + 0]))); SetOrgAll(Clock(NextE(ta[i*M + 0])), OrgV(Clock(NextE(ta[i*M + 0])))); SetOrgAll(Clock(NextE(NextE(ta[i*M + 0]))), OrgV(Clock(NextE(NextE(ta[i*M + 0]))))); SetOrgAll(Clock(NextE(NextE(NextE(ta[i*M + 0])))), OrgV(Clock(NextE(NextE(NextE(ta[i*M + 0])))))); SetPneg(ta[i*M + 0], PnegP(tb[i*M + 0])); SetPneg(PrevE(ta[i*M + 0]), PnegP(PrevE(tb[i*M + 0]))); SetPneg(PrevE(PrevE(ta[i*M + 0])), PnegP(PrevE(PrevE(tb[i*M + 0])))); SetPneg(PrevE(PrevE(PrevE(ta[i*M + 0]))), PnegP(PrevE(PrevE(PrevE(tb[i*M + 0]))))); } for (i = 0; i < n; i++) { for (j = 1; j < n; j++) { Meld(tb[i*M + j],ta[i*M + j]); /* Update the edge slots */ SetRingEdgeInfo(ta[i*M + j], PWedge(ta[i*M + j])->edge); SetRingEdgeInfo(NextE(ta[i*M + j]), PWedge(NextE(ta[i*M + j]))->edge); SetRingEdgeInfo(NextE(NextE(ta[i*M + j])), PWedge(NextE(NextE(ta[i*M + j])))->edge); SetRingEdgeInfo(NextE(NextE(NextE(ta[i*M + j]))), PWedge(NextE(NextE(NextE(ta[i*M + j]))))->edge); /* Update the node slots */ SetOrgAll(ta[i*M + j], OrgV(ta[i*M + j])); SetOrgAll(NextE(ta[i*M + j]), OrgV(NextE(ta[i*M + j]))); SetOrgAll(NextE(NextE(ta[i*M + j])), OrgV(NextE(NextE(ta[i*M + j])))); SetOrgAll(NextE(NextE(NextE(ta[i*M + j]))), OrgV(NextE(NextE(NextE(ta[i*M + j]))))); SetOrgAll(Clock(ta[i*M + j]), OrgV(Clock(ta[i*M + j]))); SetOrgAll(Clock(NextE(ta[i*M + j])), OrgV(Clock(NextE(ta[i*M + j])))); SetOrgAll(Clock(NextE(NextE(ta[i*M + j]))), OrgV(Clock(NextE(NextE(ta[i*M + j]))))); SetOrgAll(Clock(NextE(NextE(NextE(ta[i*M + j])))), OrgV(Clock(NextE(NextE(NextE(ta[i*M + j])))))); SetPneg(ta[i*M + j], PnegP(tb[i*M + j])); SetPneg(PrevE(ta[i*M + j]), PnegP(PrevE(tb[i*M + j]))); SetPneg(PrevE(PrevE(ta[i*M + j])), PnegP(PrevE(PrevE(tb[i*M + j])))); SetPneg(PrevE(PrevE(PrevE(ta[i*M + j]))), PnegP(PrevE(PrevE(PrevE(tb[i*M + j]))))); } } return ta[0*M + 0]; } FourPlaces_vec_t Make1DCubearray(uint order) { SixPlaces_vec_t ca = SixPlaces_vec_new(order); FourPlaces_vec_t cb = FourPlaces_vec_new(order); int i, j; for (i = 0; i < order; i++) { ca.e[i] = MakeCube(); cb.e[i].p[0] = ca.e[i].p[1]; cb.e[i].p[1] = ca.e[i].p[3]; cb.e[i].p[2] = ca.e[i].p[0]; cb.e[i].p[3] = ca.e[i].p[5]; } /* Glue the cubes: */ for (j = 0; j < order-1; j++) { GlueCube(ca.e[j].p[2], PrevF(ca.e[j+1].p[3])); } return cb; } TwoPlaces_vec_t Make2DCubeArray(uint order) { FourPlaces_vec_t cb = FourPlaces_vec_new(order* order); TwoPlaces_vec_t cc = TwoPlaces_vec_new(order*order); /* Assembling the array {cb} */ int i,j,k; for (i = 0; i < order; i++) { FourPlaces_vec_t ca = Make1DCubearray(order); for (j = 0; j < order; j++) { for (k = 0; k < 4; k++) { cb.e[i*order + j].p[k] = ca.e[j].p[k]; } } } /* Gluing the rows: */ for (j = 0; j < (order-1); j++) { for (k = 0; k < order; k++) { GlueCube(cb.e[j*order + k].p[1], Clock(NextE(NextE(cb.e[(j+1)*order + k].p[0])))); } } /* Selecting the places to return: */ for (i = 0; i < order; i++) { for (j = 0; j < order; j++) { for (k = 0; k < 2; k++) { cc.e[i*order + j].p[k] = cb.e[i*order + j].p[k+2]; } } } return cc; } TwoPlaces_vec_t MakeBigCube(uint order) { FourPlaces_vec_t cd = FourPlaces_vec_new(order*order*order); TwoPlaces_vec_t ce = TwoPlaces_vec_new(order*order); int i,j,k,l; for (i = 0; i < order; i++) { TwoPlaces_vec_t cc = Make2DCubeArray(order); for (j = 0; j < order; j++) { for (k = 0; k < order; k++) { for (l = 0; l < 2; l++) { cd.e[(i*order + j)*order + k].p[l] = cc.e[j*order + k].p[l]; } } } } /* Gluing: */ for (i = 0; i < (order-1); i++) { for (k = 0; k < order; k++) { for (j = 0; j < order; j++) { Place_t pikj = cd.e[(i*order + k)*order +j].p[1]; Place_t qikj = cd.e[((i+1)*order +k)*order + j].p[0]; GlueCube(pikj, Clock(qikj)); } } } /* Selecting the places for return */ for (j = 0; j < order; j++) { for (k = 0; k < order; k++) { ce.e[j*order + k].p[0] = cd.e[(0*order + k)*order + j].p[0]; ce.e[j*order + k].p[1] = cd.e[((order-1)*order + k)*order + j].p[1]; } } return ce; } bool_t WallOnBoundary(Place_t p); /* [!!! Define it somewhere !!!] */ void SetCubeProperties(TwoPlaces_vec_t *a, uint n, ElemTableRec_t *top) { uint index = 0; Place_vec_t c1 = Place_vec_new(n); Place_vec_t c2 = Place_vec_new(n); Place_vec_t c3 = Place_vec_new(n); Place_vec_t c4 = Place_vec_new(n); /* Set the original nodes */ SetExNode(Clock(NextE(a->e[0*n + 0].p[0])), FALSE); /* node 1 */ SetExNode(Clock(a->e[(n-1)*n + 0].p[0]), FALSE); /* node 2 */ SetExNode(a->e[(n-1)*n + (n-1)].p[0], FALSE); /* node 3 */ SetExNode(a->e[(n-1)*n + 0].p[1], FALSE); /* node 4 */ SetExNode(Clock(a->e[(n-1)*n + (n-1)].p[1]), FALSE); /* node 5 */ SetExNode(Clock(NextE(a->e[0*n + (n-1)].p[1])), FALSE); /* node 6 */ SetExNode(PrevE(a->e[0*n + 0].p[1]), FALSE); /* node 7 */ SetExNode(PrevE(a->e[0*n + (n-1)].p[0]), FALSE); /* node 8 */ /* Set the original edgess */ int i, j, k; for (i = 0; i < n; i++) { SetExEdge(PrevE(a->e[i*n + 0].p[1]), FALSE); SetExEdge(NextE(a->e[i*n + 0].p[0]), FALSE); SetExEdge(a->e[(n-1)*n + i].p[0], FALSE); SetExEdge(a->e[(n-1)*n + i].p[1], FALSE); SetExEdge(PrevE(a->e[(i)*n + (n-1)].p[0]), FALSE); SetExEdge(NextE(a->e[(i)*n + (n-1)].p[1]), FALSE); SetExEdge(NextE(NextE(a->e[0*n + i].p[1])), FALSE); SetExEdge(NextE(NextE(a->e[0*n + i].p[0])), FALSE); } /* computing @{edge->?}s on the colums */ c1.e[0] = NextE(NextF(a->e[(n-1)*n + 0].p[0])); c2.e[0] = PrevE(NextF(a->e[(n-1)*n + (n-1)].p[0])); c3.e[0] = NextE(NextF(NextE(a->e[0*n + 0].p[0]))); c4.e[0] = PrevE(NextF(PrevE(a->e[0*n + (n-1)].p[0]))); for (k = 1; k < n; k++) { c1.e[k] = Clock(PrevE(PrevF(NextE(c1.e[k-1])))); c2.e[k] = Clock(NextE(PrevF(PrevE(c2.e[k-1])))); c3.e[k] = Clock(PrevE(PrevF(NextE(c3.e[k-1])))); c4.e[k] = Clock(NextE(PrevF(PrevE(c4.e[k-1])))); } /* Now set the original edgess */ for (j = 0; j < n; j++) { SetExEdge(c1.e[j], FALSE); SetExEdge(c2.e[j], FALSE); SetExEdge(c3.e[j], FALSE); SetExEdge(c4.e[j], FALSE); } for (i = 0; i < top->wall.ne; i++) { Place_t f = top->wall.e[i]; { if (WallOnBoundary(f)){ SetExWall(f, FALSE); index++; } } } assert(index == 6*n*n); } TwoPlaces_vec_t BuildBigRawCube(uint order, bool_t original) { TwoPlaces_vec_t cd = TwoPlaces_vec_new(order*order*order); int i,j,k,l; for (i = 0; i < order; i++) { TwoPlaces_vec_t cc = Make2DCubeArray(order); for (j = 0; j < order; j++) { for (k = 0; k < order; k++) { for (l = 0; l < 2; l++) { cd.e[(i*order + j)*order + k].p[l] = cc.e[j*order + k].p[l]; } } } } /* Gluing: */ for (i = 0; i < (order-1); i++) { for (k = 0; k < order; k++) { for (j = 0; j < order; j++) { Place_t pikj = cd.e[(i*order + k)*order + j].p[1]; Place_t qikj = cd.e[((i+1)*order + k)*order + j].p[0]; GlueCube(pikj, Clock(qikj)); } } } return cd; } #define BigCube_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 30-08-2000 : [???] Nice version of the {MakeOctahedron} procedure.\n" \ " 19-09-2000 : [???] Added the procedure "MakeDodecahedronTriang".\n" \ " 27-10-2000 : [???] Modified {SetCubeProperties} procedure.\n" \ " 04-11-2000 : [???] Added the {CubeNegNodes} and {CubeBarycenter} procedures.\n" \ " 26-01-2007 : [???] Moved {MakeBigRawCube} from {MakeBigCubeFixed.c} to here." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Cube.c /* See {Cube.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:44:48 by stolfi */ #define Cube_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include void SetCubeInteriorCell(Place_t p, Cell_t n); /* Set to {n} the cell slot of the 24 places of the cube's interior. */ EightNodes_t CubeNegNodes(Place_t a) /* Valid for the versions Spin(a), Clock(a) and SpinClock(a). ? */ { assert(Pneg(a)!=NULL); Node_t n0 = OrgV(a); Node_t n1 = OrgV(PrevE(a)); Node_t n2 = OrgV(PrevE(PrevE(a))); Node_t n3 = OrgV(PrevE(PrevF(PrevE(a)))); assert((n0 != n1)); assert((n0 != n2) && (n1 != n2)); assert((n0 != n3) && (n1 != n3) && (n2 != n3)); Place_t b = Clock(NextF(PrevE(PrevE(PrevF(a))))); assert(Pneg(a) == Ppos(b)); Node_t m0 = OrgV(b); Node_t m1 = OrgV(PrevE(b)); Node_t m2 = OrgV(PrevE(PrevE(b))); Node_t m3 = OrgV(PrevE(PrevF(PrevE(b)))); assert((m0 != m1)); assert((m0 != m2) && (m1 != m2)); assert((m0 != m3) && (m1 != m3) && (m2 != m3)); return (EightNodes_t){{n0,n1,n2,n3,m0,m1,m2,m3}}; } r4_t CubeBarycenter(Place_t a, Coords_t *c) { r4_t sum = (r4_t){{0,0,0,0}}; EightNodes_t v = CubeNegNodes(a); int i; for (i = 0; i < 8; i++) { r4_t *pi = &(c->e[v.v[i]->num]); r4_add(pi, &sum, &sum); } r4_scale(1.0/8.0, &sum, &sum); return sum; } SixPlaces_t MakeCube() { auto Place_t CEE(Place_t p); /* Short for {Clock(NextE(NextE(p)))}. */ Place_t CEE(Place_t p) { return Clock(NextE(NextE(p))); } SixPlaces_t co; int i; for (i = 0; i < 6; i++){ co.p[i] = MakeSquare(); } /* Glue Walls */ SetNextF(co.p[1], CEE(co.p[2])); /* 1-2 */ SetEdgeInfo(co.p[1], PEdge(CEE(co.p[2]))); SetOrgAll(co.p[1], OrgV(co.p[1])); SetOrgAll(Clock(co.p[1]), OrgV(Clock(co.p[1]))); SetNextF(co.p[2], CEE(co.p[3])); /* 2-3 */ SetEdgeInfo(co.p[2], PEdge(CEE(co.p[3]))); SetOrgAll(co.p[2], OrgV(co.p[2])); SetOrgAll(Clock(co.p[2]), OrgV(Clock(co.p[2]))); SetNextF(co.p[3], CEE(co.p[4])); /* 3-4 */ SetEdgeInfo(co.p[3], PEdge(CEE(co.p[4]))); SetOrgAll(co.p[3], OrgV(co.p[3])); SetOrgAll(Clock(co.p[3]), OrgV(Clock(co.p[3]))); SetNextF(co.p[4], CEE(co.p[1])); /* 4-1 */ SetEdgeInfo(co.p[4], PEdge(CEE(co.p[1]))); SetOrgAll(co.p[4], OrgV(co.p[4])); SetOrgAll(Clock(co.p[4]), OrgV(Clock(co.p[4]))); SetNextF(PrevE(co.p[1]), Clock(NextE(co.p[0]))); /* 1-0 */ SetEdgeInfo(PrevE(co.p[1]), PEdge(Clock(NextE(co.p[0])))); SetOrgAll(PrevE(co.p[1]), OrgV(PrevE(co.p[1]))); SetOrgAll(Clock(PrevE(co.p[1])), OrgV(Clock(PrevE(co.p[1])))); SetNextF(PrevE(co.p[5]), Clock(NextE(co.p[1]))); /* 5-1 */ SetEdgeInfo(PrevE(co.p[5]), PEdge(Clock(NextE(co.p[1])))); SetOrgAll(PrevE(co.p[5]), OrgV(PrevE(co.p[5]))); SetOrgAll(Clock(PrevE(co.p[5])), OrgV(Clock(PrevE(co.p[5])))); SetNextF(co.p[5], Clock(NextE(co.p[2]))); /* 5-2 */ SetEdgeInfo(co.p[5], PEdge(Clock(NextE(co.p[2])))); SetOrgAll(co.p[5], OrgV(co.p[5])); SetOrgAll(Clock(co.p[5]), OrgV(Clock(co.p[5]))); SetNextF(NextE(co.p[5]), Clock(NextE(co.p[3]))); /* 5-3 */ SetEdgeInfo(NextE(co.p[5]), PEdge(Clock(NextE(co.p[3])))); SetOrgAll(NextE(co.p[5]), OrgV(NextE(co.p[5]))); SetOrgAll(Clock(NextE(co.p[5])), OrgV(Clock(NextE(co.p[5])))); SetNextF(NextE(NextE(co.p[5])), Clock(NextE(co.p[4]))); /* 5-4 */ SetEdgeInfo(NextE(NextE(co.p[5])), PEdge(Clock(NextE(co.p[4])))); SetOrgAll(NextE(NextE(co.p[5])), OrgV(NextE(NextE(co.p[5])))); SetOrgAll(Clock(NextE(NextE(co.p[5]))), OrgV(Clock(NextE(NextE(co.p[5]))))); SetNextF(co.p[0], Clock(PrevE(co.p[2]))); /* 0-2 */ SetEdgeInfo(co.p[0], PEdge(Clock(PrevE(co.p[2])))); SetOrgAll(co.p[0], OrgV(co.p[0])); SetOrgAll(Clock(co.p[0]), OrgV(Clock(co.p[0]))); SetNextF(PrevE(co.p[0]), Clock(PrevE(co.p[3]))); /* 0-3 */ SetEdgeInfo(PrevE(co.p[0]), PEdge(Clock(PrevE(co.p[3])))); SetOrgAll(PrevE(co.p[0]), OrgV(PrevE(co.p[0]))); SetOrgAll(Clock(PrevE(co.p[0])), OrgV(Clock(PrevE(co.p[0])))); SetNextF(NextE(NextE(co.p[0])), Clock(PrevE(co.p[4]))); /* 0-4 */ SetEdgeInfo(NextE(NextE(co.p[0])), PEdge(Clock(PrevE(co.p[4])))); SetOrgAll(NextE(NextE(co.p[0])), OrgV(NextE(NextE(co.p[0])))); SetOrgAll(Clock(NextE(NextE(co.p[0]))), OrgV(Clock(NextE(NextE(co.p[0]))))); Cell_t q = MakeCell(); q->num = 0; SetCubeInteriorCell(co.p[0], q); return co; } Place_t GlueCube(Place_t a, Place_t b) /* Make the glueing of two simples cubes around of one squared wall common. The place {a} and theirs adjacents with the same wall component is killed. */ { Meld(a,b); /* Update the edge slots: */ SetRingEdgeInfo(b, PEdge(b)); SetRingEdgeInfo(NextE(b), PEdge(NextE(b))); SetRingEdgeInfo(NextE(NextE(b)), PEdge(NextE(NextE(b)))); SetRingEdgeInfo(NextE(NextE(NextE(b))), PEdge(NextE(NextE(NextE(b))))); /* Update the node slots: */ SetOrgAll(b, OrgV(b)); SetOrgAll(NextE(b), OrgV(NextE(b))); SetOrgAll(NextE(NextE(b)), OrgV(NextE(NextE(b)))); SetOrgAll(NextE(NextE(NextE(b))), OrgV(NextE(NextE(NextE(b))))); SetOrgAll(Clock(b), OrgV(Clock(b))); SetOrgAll(Clock(NextE(b)), OrgV(Clock(NextE(b)))); SetOrgAll(Clock(NextE(NextE(b))), OrgV(Clock(NextE(NextE(b))))); SetOrgAll(Clock(NextE(NextE(NextE(b)))), OrgV(Clock(NextE(NextE(NextE(b)))))); /* Update the cell slots: */ SetPneg(b, PnegP(a)); SetPneg(PrevE(b), PnegP(PrevE(a))); SetPneg(PrevE(PrevE(b)), PnegP(PrevE(PrevE(a)))); SetPneg(PrevE(PrevE(PrevE(b))), PnegP(PrevE(PrevE(PrevE(a))))); return b; } void SetCubeInteriorCell(Place_t p, Cell_t n) { Place_t t = p; SetPnegOfNearbyWalls(t, n); do { SetPnegOfNearbyWalls(Clock(PrevF(t)),n); t = PrevE(t); } while (t != p); t = PrevF(PrevE(PrevE(PrevF(p)))); SetPnegOfNearbyWalls(t,n); } void FixCoordsCube(SixPlaces_t *ca, ElemTableRec_t *top, Coords_t *c) { r4_t o1 = (r4_t){{ 1.0, 1.0, 1.0,1.0}}; /* the node ( 1, 1, 1,1) */ r4_t o2 = (r4_t){{ 1.0, 1.0,-1.0,1.0}}; /* the node ( 1, 1,-1,1) */ r4_t o3 = (r4_t){{ 1.0,-1.0, 1.0,1.0}}; /* the node ( 1,-1, 1,1) */ r4_t o4 = (r4_t){{ 1.0,-1.0,-1.0,1.0}}; /* the node ( 1,-1,-1,1) */ r4_t o5 = (r4_t){{-1.0, 1.0, 1.0,1.0}}; /* the node (-1, 1, 1,1) */ r4_t o6 = (r4_t){{-1.0, 1.0,-1.0,1.0}}; /* the node (-1, 1,-1,1) */ r4_t o7 = (r4_t){{-1.0,-1.0, 1.0,1.0}}; /* the node (-1,-1, 1,1) */ r4_t o8 = (r4_t){{-1.0,-1.0,-1.0,1.0}}; /* the node (-1,-1,-1,1) */ auto void SetCornerCoords(Place_t e, r4_t *cv); void SetCornerCoords(Place_t e, r4_t *cv) { c->e[OrgV(e)->num] = (*cv); } /* Set the corners */ SetCornerCoords(ca->p[5], &o1); SetCornerCoords(ca->p[1], &o2); SetCornerCoords(Clock(ca->p[4]),&o3); SetCornerCoords(ca->p[4], &o4); SetCornerCoords(Clock(ca->p[5]),&o5); SetCornerCoords(ca->p[2], &o6); SetCornerCoords(Clock(ca->p[3]),&o7); SetCornerCoords(ca->p[3], &o8); } void PrintCubePlaces(Place_t p) { auto void PrintPnegsOfWall(Place_t s); void PrintPnegsOfWall(Place_t s) { Place_t t = s; do { PrtPnegNum(t); t = PrevE(t); } while (t != s); } PrintPnegsOfWall(p); Place_t t = p; do { PrintPnegsOfWall(Clock(PrevF(t))); t = PrevE(t); } while (t != p); t = PrevF(PrevE(PrevF(p))); PrintPnegsOfWall(t); } #define Cube_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 27-10-2000 : Modified {SetCubeProperties} procedure.\n" \ " 04-11-2000 : Added the {CubeNegNodes} and {CubeBarycenter} procedures.\n" \ " 26-01-2007 : Converted to C by J. Stolfi; got {FixCoordsCube}\n" \ " from {MakeBigCubeFixed.c}." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/FunnyBall.c /* See {FunnyBall.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:46:44 by stolfi */ #define FunnyBall_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include Place_t GlueBall(Place_t a, Place_t b); /* Make the glueing of two simples 2-gon walls around of one common wall. The place {a} and its adjacent ones with the same wall component are killed. */ void SetFunnyBallInteriorCell(Place_t p, Cell_t n); /* Set to {n} the cell slots of the 8 places on the interior of the funny ball {n}. */ FourPlaces_t MakeFunnyBall(void) { FourPlaces_t co; int i; for (i = 0; i < 4; i++) { co.p[i] = MakePolygon(2); } /* Glue Walls */ for (i = 0; i < 4; i++) { SetNextF(co.p[i],Clock(NextE(co.p[(i+1) % 4]))); SetEdgeInfo(co.p[i], PWedge(Clock(NextE(co.p[(i+1) % 4])))->edge); SetOrgAll(co.p[i], OrgV(co.p[i])); SetOrgAll(Clock(co.p[i]), OrgV(Clock(co.p[i]))); } Cell_t q = MakeCell(); q->num = 0; SetFunnyBallInteriorCell(co.p[0], q); return co; } Place_t GlueBall(Place_t a, Place_t b) { assert(SpinBit(a) == SpinBit(b)); Meld(a,b); /* Update the edge slots */ SetRingEdgeInfo(b, PEdge(b)); SetRingEdgeInfo(NextE(b), PEdge(NextE(b))); /* Update the node slots */ SetOrgAll(b, OrgV(b)); SetOrgAll(NextE(b), OrgV(NextE(b))); /* Update the cell slots */ SetPneg(b, PnegP(a)); SetPneg(PrevE(b), PnegP(PrevE(a))); return b; } void SetFunnyBallInteriorCell(Place_t p, Cell_t n) { SetPnegOfNearbyWalls(p, n); Place_t t = p; do { SetPnegOfNearbyWalls(Clock(PrevF(t)),n); t = PrevE(t); } while (t != p); t = PrevF(PrevE(PrevF(p))); SetPnegOfNearbyWalls(t, n); } #define FunnyBall_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 26-01-2007 : Converted to C by J. Stolfi, extracted from {}." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Icosahedron.c /* See {Icosahedron.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:47:24 by stolfi */ #define Icosahedron_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include TwentyPlaces_t OldMakeIcosahedronTriang(void) { EightPlaces_t a[20]; TwentyPlaces_t b; /* this variable will be retuned */ int i; for (i = 0; i < 20; i++) { a[i] = MakeTetraTopo(1,1); } /* first level */ Glue(Spin(a[ 1].p[1]), a[ 0].p[0], 1, TRUE); Glue(Spin(a[ 2].p[1]), a[ 1].p[0], 1, TRUE); Glue(Spin(a[ 3].p[1]), a[ 2].p[0], 1, TRUE); Glue(Spin(a[ 4].p[1]), a[ 3].p[0], 1, TRUE); Glue(Spin(a[ 0].p[1]), a[ 4].p[0], 1, TRUE); /* next level */ Glue(Spin(a[ 0].p[3]), a[5].p[2], 1, TRUE); Glue(Spin(a[ 1].p[3]), a[6].p[2], 1, TRUE); Glue(Spin(a[ 2].p[3]), a[7].p[2], 1, TRUE); Glue(Spin(a[ 3].p[3]), a[8].p[2], 1, TRUE); Glue(Spin(a[ 4].p[3]), a[9].p[2], 1, TRUE); Glue(Spin(a[10].p[1]), a[5].p[0], 1, TRUE); Glue(Spin(a[ 6].p[1]), PrevE(a[10].p[7]), 1, TRUE); Glue(Spin(a[11].p[1]), a[ 6].p[0], 1, TRUE); Glue(Spin(a[ 7].p[1]), PrevE(a[11].p[7]), 1, TRUE); Glue(Spin(a[12].p[1]), a[ 7].p[0], 1, TRUE); Glue(Spin(a[ 8].p[1]), PrevE(a[12].p[7]), 1, TRUE); Glue(Spin(a[13].p[1]), a[ 8].p[0], 1, TRUE); Glue(Spin(a[ 9].p[1]), PrevE(a[13].p[7]), 1, TRUE); Glue(Spin(a[14].p[1]), a[ 9].p[0], 1, TRUE); Glue(Spin(a[ 5].p[1]), PrevE(a[14].p[7]), 1, TRUE); /* Last level */ Glue(Spin(NextE(a[10].p[0])), a[15].p[2], 1, TRUE); Glue(Spin(NextE(a[11].p[0])), a[16].p[2], 1, TRUE); Glue(Spin(NextE(a[12].p[0])), a[17].p[2], 1, TRUE); Glue(Spin(NextE(a[13].p[0])), a[18].p[2], 1, TRUE); Glue(Spin(NextE(a[14].p[0])), a[19].p[2], 1, TRUE); Glue(Spin(a[16].p[1]), a[15].p[0], 1, TRUE); Glue(Spin(a[17].p[1]), a[16].p[0], 1, TRUE); Glue(Spin(a[18].p[1]), a[17].p[0], 1, TRUE); Glue(Spin(a[19].p[1]), a[18].p[0], 1, TRUE); Glue(Spin(a[15].p[1]), a[19].p[0], 1, TRUE); for (i = 0; i < 5; i++) { b.p[i] = a[i].p[2]; } for (i = 5; i < 10; i++) { b.p[i] = a[i].p[3]; } for (i = 10; i < 15; i++) { b.p[i] = a[i].p[3]; } for (i = 15; i < 20; i++) { b.p[i] = a[i].p[3]; } return b; } Place_t MakeIcosahedron(void) /* From MakePlatonic.c */ { /* Create twenty triangles {a[0..19]}: */ Place_t a[20]; int i; for (i = 0; i < 20; i++) { a[i] = MakeTriangle(); } /* Glue triangles in first level: */ for (i = 0; i < 5; i++) { SetNextF(PrevE(a[i]), Clock(NextE(a[(i+1) % 5]))); SetNextF(a[i+5], Clock(a[i])); } /* Glue triangles in second level: */ for (i = 5; i < 10; i++) { if (i == 9) {SetNextF(NextE(a[i]), Clock(NextE(a[10]))); } else { SetNextF(NextE(a[i]), Clock(NextE(a[i+6]))); } } for (i = 5; i < 10; i++) { SetNextF(PrevE(a[i]), Clock(PrevE(a[i+5]))); } /* Glue triangles in third level: */ for (i = 10; i < 15; i++) { SetNextF(a[i+5], Clock(a[i])); } for (i = 15; i < 19; i++) { SetNextF(NextE(a[i]), Clock(PrevE(a[i+1]))); } SetNextF(NextE(a[19]), Clock(PrevE(a[15]))); for (i = 0; i < 20; i++) { SetOrgAll(a[i], OrgV(a[i])); SetOrgAll(NextE(a[i]), OrgV(NextE(a[i]))); SetOrgAll(PrevE(a[i]), OrgV(PrevE(a[i]))); } return a[0]; } TwentyPlaces_t MakeIcosahedronTriang(bool_t original) { EightPlaces_t a[20]; TwentyPlaces_t b; /* this variable will be retuned */ int i; for (i = 0; i < 20; i++) { a[i] = MakeTetraTopo(1,1); } /* inside the first level */ Glue(Spin(a[1].p[1]), a[0].p[0], 1, TRUE); Glue(Spin(a[2].p[1]), a[1].p[0], 1, TRUE); Glue(Spin(a[3].p[1]), a[2].p[0], 1, TRUE); Glue(Spin(a[4].p[1]), a[3].p[0], 1, TRUE); Glue(Spin(a[0].p[1]), a[4].p[0], 1, TRUE); /* between the first and second level */ Glue(Spin(a[0].p[3]), a[5].p[2], 1, TRUE); Glue(Spin(a[1].p[3]), a[6].p[2], 1, TRUE); Glue(Spin(a[2].p[3]), a[7].p[2], 1, TRUE); Glue(Spin(a[3].p[3]), a[8].p[2], 1, TRUE); Glue(Spin(a[4].p[3]), a[9].p[2], 1, TRUE); /* inside the second level */ Glue(Spin(NextE(a[10].p[1])), a[ 5].p[0], 1, TRUE); Glue( Spin(a[ 6].p[1]), NextE(a[10].p[0]), 1, TRUE); Glue(Spin(NextE(a[11].p[1])), a[ 6].p[0], 1, TRUE); Glue( Spin(a[ 7].p[1]), NextE(a[11].p[0]), 1, TRUE); Glue(Spin(NextE(a[12].p[1])), a[ 7].p[0], 1, TRUE); Glue( Spin(a[ 8].p[1]), NextE(a[12].p[0]), 1, TRUE); Glue(Spin(NextE(a[13].p[1])), a[ 8].p[0], 1, TRUE); Glue( Spin(a[ 9].p[1]), NextE(a[13].p[0]), 1, TRUE); Glue(Spin(NextE(a[14].p[1])), a[ 9].p[0], 1, TRUE); Glue( Spin(a[ 5].p[1]), NextE(a[14].p[0]), 1, TRUE); /* between the second and third level */ Glue (Spin(a[10].p[3]), a[15].p[2], 1, TRUE); Glue (Spin(a[11].p[3]), a[16].p[2], 1, TRUE); Glue (Spin(a[12].p[3]), a[17].p[2], 1, TRUE); Glue (Spin(a[13].p[3]), a[18].p[2], 1, TRUE); Glue (Spin(a[14].p[3]), a[19].p[2], 1, TRUE); /* inside the third level */ Glue(Spin(a[16].p[1]), a[15].p[0], 1, TRUE); Glue(Spin(a[17].p[1]), a[16].p[0], 1, TRUE); Glue(Spin(a[18].p[1]), a[17].p[0], 1, TRUE); Glue(Spin(a[19].p[1]), a[18].p[0], 1, TRUE); Glue(Spin(a[15].p[1]), a[19].p[0], 1, TRUE); /* Rescue the @places to be returned */ for (i = 0; i < 5; i++){ b.p[i] = a[i].p[2]; } for (i = 5; i < 10; i++){ b.p[i] = a[i].p[3]; } for (i = 10; i < 15; i++){ b.p[i] = a[i].p[2]; } for (i = 15; i < 20; i++){ b.p[i] = a[i].p[3]; } if (original) { /* emphasize the original elements */ SetExWallsOfEdge(a[0].p[1], FALSE); SetExEdge(a[0].p[1], FALSE); SetExWallsOfEdge(a[15].p[1], FALSE); SetExEdge(a[15].p[1], FALSE); SetExNode(a[15].p[1], FALSE); for (i = 0; i < 5; i++) { SetExWallsOfEdge(NextE(a[i].p[1]), FALSE); } for (i = 5; i < 10; i++) { SetExEdge(PrevE(a[i].p[1]), FALSE); } for (i = 15; i < 20; i++) { SetExWallsOfEdge(PrevE(a[i].p[1]), FALSE); SetExEdge(PrevE(a[i].p[1]), FALSE); } } /* Check some assertions: */ for (i = 0; i < 5; i++) { assert(NextF(b.p[i+5]) == Spin(b.p[i]));} for (i = 10; i < 15; i++) { assert(NextF(b.p[i+5]) == Spin(b.p[i])); } return b; } #define Icosahedron_C_author \ "Modula-3 procedures created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 24-01-2007 : Converted to C by J. Stolfi;\n" \ " got {MakeIcosahedron} from {MakePlatonic.c};\n" \ " got {OldMakeIcosahedronTriang}, {MakeIcosahedronTriang}\n" \ " from {Squared.c}." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Octahedron.c /* See {Octahedron.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:48:07 by stolfi */ #define Octahedron_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include FourPlaces_t MakeHalfOct(void); /* Builds half octahedron without cell information. */ FourPlaces_t MakeHalfOct(void) /* [!!!] From {Squared.c} */ { FourPlaces_t p; int i; for (i = 0; i < 4; i++){ p.p[i] = MakeTriangle(); } for (i = 0; i < 4; i++) { Place_t a = NextE(p.p[i]); Place_t b = Clock(PrevE(p.p[(i+1) % 4])); { SetNextF(a, b); SetRingEdgeInfo(a, PEdge(a)); } } for (i = 0; i < 4; i++) { SetOrgAll(PrevE(p.p[i]), OrgV(PrevE(p.p[i]))); } return p; } EightPlaces_t MakeOctahedron(void) /* From {VStar.c}/{Squared.c}/{MakePlatonic.c} */ { EightPlaces_t p ; FourPlaces_t sup = MakeHalfOct(); FourPlaces_t inf = MakeHalfOct(); /* Builds an octahedron with two half-octahedra {s} (superior) and {i} (inferior). */ int j; for (j = 0; j < 4; j++) { p.p[j] = sup.p[j]; } for (j = 4; j < 8; j++) { p.p[j] = inf.p[j-4]; } /* Set the shared elements: */ for (j = 0; j < 4; j++) { SetNextF(p.p[j],p.p[j+4]); SetRingEdgeInfo(p.p[j],PEdge(p.p[j])); SetOrgAll(p.p[j], OrgV(p.p[j])); SetOrgAll(NextE(p.p[j]), OrgV(NextE(p.p[j]))); } /* Set the cell attribute; the 24 places have the same cell. */ Cell_t q = MakeCell(); q->num = 0; int i; for (i = 0; i < 8; i++) { SetPnegOfWall(p.p[i], q); } /* This test is applies for assert that any place {p[i]} really underly on a topological octahedron.*/ for (i = 0; i < 8; i++) { int d = DegreeOfNode(Srot(p.p[i])); assert(d == 8); } return p; } EightPlaces_t MakeOctahedronTriang(bool_t original) /* From {Squared.c} */ { EightPlaces_t a[8]; EightPlaces_t b; int i; for (i = 0; i < 8; i++) { a[i] = MakeTetraTopo(1,1); } /* first level gluing tetrahedra */ Glue(Spin(a[1].p[1]),a[0].p[0],1, TRUE); Glue(Spin(a[2].p[1]),a[1].p[0],1, TRUE); Glue(Spin(a[3].p[1]),a[2].p[0],1, TRUE); Glue(Spin(a[0].p[1]),a[3].p[0],1, TRUE); /* second level gluing tetrahedra */ Glue(Spin(a[0].p[3]),a[4].p[2],1, TRUE); Glue(Spin(a[1].p[3]),a[5].p[2],1, TRUE); Glue(Spin(a[2].p[3]),a[6].p[2],1, TRUE); Glue(Spin(a[3].p[3]),a[7].p[2],1, TRUE); /* gluing between levels */ Glue(Spin(a[5].p[1]),a[4].p[0],1, TRUE); Glue(Spin(a[6].p[1]),a[5].p[0],1, TRUE); Glue(Spin(a[7].p[1]),a[6].p[0],1, TRUE); Glue(Spin(a[4].p[1]),a[7].p[0],1, TRUE); if (original) { /* Emphasize the original elements */ SetExWallsOfEdge(a[0].p[1],FALSE); SetExWallsOfEdge(a[4].p[1],FALSE); SetExEdge(a[0].p[1],FALSE); SetExEdge(a[4].p[1],FALSE); for (i = 0; i < 4; i++) { SetExWallsOfEdge(NextE(a[i].p[1]),FALSE); } for (i = 4; i < 8; i++) { SetExEdge(PrevE(a[i].p[1]),FALSE); } SetExNode(a[4].p[1], FALSE); } b.p[0] = a[0].p[2]; b.p[1] = a[1].p[2]; b.p[2] = a[2].p[2]; b.p[3] = a[3].p[2]; b.p[4] = a[4].p[3]; b.p[5] = a[5].p[3]; b.p[6] = a[6].p[3]; b.p[7] = a[7].p[3]; return b; } #define Octahedron_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 30-08-2000 : Nice version of the {MakeOctahedron} procedure." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Polygon.c /* See {Polygon.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:48:44 by stolfi */ #define Polygon_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include Place_t MakePolygon(uint n) { Place_t sp[n]; Node_t sv[n]; int i; for (i = 0; i < n; i++) { sp[i] = MakeWedge(); sv[i] = MakeNode(); } Wall_t f = PWall(sp[0]); for (i = 0; i < n; i++) { PWedge(sp[i])->num = 0; SetOrg(sp[i],sv[i]); SetOrg(Clock(sp[i]),sv[(i+1) % n]); SetNextE(sp[i],sp[(i+1) % n]); SetWallInfo(sp[i],f); } return sp[0]; } Place_vec_t MakePolygonFull(uint n) { Place_vec_t sp = Place_vec_new(n); Node_t sv[n]; int i; for (i = 0; i < n; i++) { sp.e[i] = MakeWedge(); sv[i] = MakeNode(); } Wall_t f = PWall(sp.e[0]); for (i = 0; i < n; i++) { PWedge(sp.e[i])->num = 0; SetOrg(sp.e[i],sv[i]); SetOrg(Clock(sp.e[i]),sv[(i+1) % n]); SetNextE(sp.e[i],sp.e[(i+1) % n]); SetWallInfo(sp.e[i],f); } return sp; } void FixCoordsGon(uint order, Place_t p, ElemTableRec_t *top, Coords_t *c) { auto void SetCoords(Place_t e, r4_t cv); /* set the coordinates of the node OrgV(e). */ auto void SetCoords(Place_t e, r4_t cv) { c->e[OrgV(e)->num] = cv; } Place_t q = p; int i; for (i = 0; i < order; i++) { double theta = 2*i*M_PI/order; double x = cos(theta); double y = sin(theta); SetCoords(q, (r4_t){{x,y,0,1}}); q = NextE(q); } } #define Polygon_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ " 26-01-2007 : Converted to C by J. Stolfi; got {FixCoordsGon} from\n" \ " {MakePolygon.c}" // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Pyramid.c /* See {Pyramid.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:50:27 by stolfi */ #define Pyramid_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include #include Place_vec_t MakePyramid(uint n) { Place_t t[n]; Place_vec_t b = MakePolygonFull(n); /* Create the {n} triangular walls */ int i, j; for (i = 0; i < n; i++) { t[i] = MakeTriangle(); } /* Connections between the base and the triangular walls */ for (i = 0; i < n; i++) { SetNextF(t[i], b.e[i]); } /* Connections between the triangular walls */ for (i = 0; i < n; i++) { SetNextF(NextE(t[i]), Clock(PrevE(t[(i+1) % n ]))); } /* Set the common elements: edges and nodes */ for (j = 0; j < n; j++) { Place_t a = t[j]; Place_t b = NextE(a); Place_t c = PrevE(a); { SetRingEdgeInfo(a, PEdge(a)); SetOrgAll(a, OrgV(a)); SetRingEdgeInfo(b, PEdge(b)); SetOrgAll(b, OrgV(b)); SetRingEdgeInfo(c, PEdge(c)); SetOrgAll(c, OrgV(c)); } } return b; } Place_t BuildElongatedBipyr(uint n) { demand (n >= 3, "order too small"); EightPlaces_t a[4*n]; /* Create the tetrahedra: */ int i; for (i = 0; i < 4*n; i++) { a[i] = MakeTetraTopo(1,1); } /* Meld the first level: */ for (i = 0; i < n; i++) { Glue(Spin(a[(i+1) % n].p[1]),a[i].p[0], 1, TRUE); } /* Meld the middle level: */ for (i = 0; i < n; i++) { Glue(Spin(a[i].p[3]), a[i+n].p[2], 1, TRUE); } for (i = n; i < 2*n; i++) { Glue(Clock(PrevE(a[i].p[0])), a[i+n].p[0], 1, TRUE); if (i == 2*n-1) { Glue( Clock(PrevE(a[n].p[1])), a[n+i].p[1], 1, TRUE); } else { Glue( Clock(PrevE(a[i+1].p[1])), a[n+i].p[1],1, TRUE); } } /* Meld the last level: */ for (i = 2*n; i < 3*n; i++) { Glue(Spin(a[i].p[2]), a[i+n].p[7], 1, TRUE); } for (i = 3*n; i < 4*n; i++) { if (i == 4*n-1) { Glue(Spin(a[3*n].p[1]), a[i].p[0], 1, TRUE); } else { Glue(Spin(a[i+1].p[1]), a[i].p[0], 1, TRUE); } } /* Emphasize the original elements: */ SetExWallsOfEdge(a[0].p[1], FALSE); SetExEdge(a[0].p[1], FALSE); SetExWallsOfEdge(a[2*n-1].p[1], FALSE); SetExEdge(a[4*n-1].p[1], FALSE); SetExNode(a[2*n-1].p[1], FALSE); for (i = 0; i < n; i++) { SetExWallsOfEdge(NextE(a[i].p[1]), FALSE); } for (i = n; i < 2*n; i++) { SetExEdge(PrevE(a[i].p[1]), FALSE); } for (i = 3*n; i < 4*n; i++) { SetExWallsOfEdge(PrevE(a[i].p[1]), FALSE); SetExEdge(PrevE(a[i].p[1]), FALSE); } return a[0].p[1]; } Place_t BuildSimpleBipyr(uint n, bool_t open) { /* Create {n} tetrahedra {a[0..n-1]}: */ EightPlaces_t a[n]; int i; for (i = 0; i < n; i++) { a[i] = MakeTetraTopo(1,1); } /* Glue them: */ for (i = 0; i < n - 1; i++) { Glue(Spin(a[i].p[1]), a[(i+1) % n].p[0], 1, TRUE); } if (open) { fprintf(stderr, "topology: openring(%d)\n", n); } else { fprintf(stderr, "topology: bipyramid(%d)\n", n); Glue(Spin(a[n-1].p[1]), a[0].p[0], 1, TRUE); /* Emphasize the original elements */ SetExWallsOfEdge(a[0].p[1], FALSE); SetExEdge(a[0].p[1], FALSE); } return a[0].p[1]; } void FixCoordsBipyramid(Place_t p, uint order, bool_t pyramid, ElemTableRec_t *top, Coords_t *c) { int n = order; /* First, compute the coordinates on a circle of radius one: */ double dt = 2*M_PI/n; auto void SetCoords(Place_t e, r4_t cv); /* Sets the coordinates of the node {OrgV(e)} to {cv}. */ void SetCoords(Place_t e, r4_t cv) { c->e[OrgV(e)->num] = cv; } Place_t q = p; int i; for (i = 0; i < n; i++) { double theta = i*dt; double x = cos(theta), y = sin(theta); SetCoords(PrevE(q), (r4_t){{x, y, 0.0, 1.0}}); q = NextF(q); } /* Now set the coordinates of the axis endpoints: */ SetCoords(Clock(p), (r4_t){{0.0, 0.0, 1.0, 1.0}}); if (pyramid) { SetCoords(p, (r4_t){{0.0, 0.0, 0.0, 1.0}}); } else { SetCoords(p, (r4_t){{0.0, 0.0, -1.0, 1.0}}); } } #define Pyramid_C_author \ "Created by L. A. P. Lozada, 1999-2000.\n" \ "Modification history:\n" \ " 26-01-2007 : [???] Moved {MakePyramid}, {BuildElongatedBipyr},\n" \ " {BuildSimpleBipyr}, from {MakeElongBip.c} and\n" \ " {MakePyramid.c} to here." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Square.c /* See {Square.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:51:00 by stolfi */ #define Square_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include Place_t MakeSquare() { Place_t a = MakeWedge(); Place_t b = MakeWedge(); Place_t c = MakeWedge(); Place_t d = MakeWedge(); Wall_t f = PWall(a); Node_t u = MakeNode(); Node_t v = MakeNode(); Node_t w = MakeNode(); Node_t x = MakeNode(); PWedge(a)->num = 0; SetOrg(a, u); SetOrg(Clock(a),v); PWedge(b)->num = 0; SetNextE(a,b); SetWallInfo(b,f); SetOrg(b,v); SetOrg(Clock(b),w); PWedge(c)->num = 0; SetNextE(b,c); SetWallInfo(c,f); SetOrg(c, w); SetOrg(Clock(c), x); PWedge(d)->num = 0; SetNextE(c,d); SetWallInfo(d,f); SetOrg(d, x); SetOrg(Clock(d), OrgV(a)); return a; } #define Square_C_author \ "Created by L. A. P. Lozada, 2000." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Squared.c /* See {Squared.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:51:08 by stolfi */ #define Squared_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include void SetExWallsOfEdge(Place_t p, bool_t exists) { Place_t q = p; do { PWall(q)->exists = exists; q = NextF(q); } while (q != p); } void SetExEdge(Place_t p, bool_t exists) { PEdge(p)->exists = exists; } void SetExNode(Place_t p, bool_t exists) { OrgV(p)->exists = exists; } #define Squared_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 30-08-2000 : Nice version of the {MakeOctahedron} procedure.\n" \ " 19-09-2000 : Added the procedure {MakeDodecahedronTriang}.\n" \ " 27-10-2000 : Modified {SetCubeProperties} procedure.\n" \ " 04-11-2000 : Added the {CubeNegNodes} and {CubeBarycenter} procedures." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Tetrahedron.c /* See {Tetrahedron.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:51:26 by stolfi */ #define Tetrahedron_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include FourPlaces_t MakeTetrahedron(void) { FourPlaces_t co; int i; for (i = 0; i < 4; i++) { co.p[i] = MakeTriangle(); } /* Glue Walls */ SetNextF(co.p[3],Clock(co.p[0])); SetEdgeInfo(co.p[3], PEdge(Clock(co.p[0]))); SetNextF(Clock(co.p[1]), NextE(co.p[0])); SetEdgeInfo(Clock(co.p[1]), PEdge(NextE(co.p[0]))); SetNextF(Clock(PrevE(co.p[0])), co.p[2]); SetEdgeInfo(Clock(PrevE(co.p[0])), PEdge(co.p[2])); SetNextF(Clock(PrevE(co.p[1])), NextE(co.p[2])); SetEdgeInfo(Clock(PrevE(co.p[1])), PEdge(NextE(co.p[2]))); SetNextF(Clock(NextE(co.p[1])), PrevE(co.p[3])); SetEdgeInfo(Clock(NextE(co.p[1])), PEdge(PrevE(co.p[3]))); SetNextF(Clock(PrevE(co.p[2])), NextE(co.p[3])); SetEdgeInfo(Clock(PrevE(co.p[2])), PEdge(NextE(co.p[3]))); SetOrgAll(co.p[0], OrgV(co.p[0])); SetOrgAll(Clock(co.p[0]), OrgV(Clock(co.p[0]))); SetOrgAll(co.p[1], OrgV(co.p[1])); SetOrgAll(PrevE(co.p[1]), OrgV(PrevE(co.p[1]))); Cell_t q = MakeCell(); q->num = 0; SetPnegOfNearbyWalls(co.p[0], q); return co; } #define Tetrahedron_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 30-08-2000 : [???] Nice version of the {MakeOctahedron} procedure.\n" \ " 19-09-2000 : [???] Added the procedure {MakeDodecahedronTriang}.\n" \ " 27-10-2000 : [???] Modified {SetCubeProperties} procedure.\n" \ " 04-11-2000 : [???] Added the {CubeNegNodes} and {CubeBarycenter} procedures." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Tools.c /* See {Tools.h} */ // #INCLUDE #define Tools_C_COPYRIGHT \ "Copyright © 1999, 2007 Universidade Estadual de Campinas (UNICAMP)" #define Tools_C_author \ "Created by L. P. Lozada, 1999." // #INCLUDE // #INCLUDE #include void PrtDFR(Place_t p) { PrintPlace(stderr, p, 5, FALSE); fprintf(stderr," DFR = %d\n", DegreeOfWall(p)); } void PrtDER(Place_t p) { PrintPlace(stderr, p, 5, FALSE); fprintf(stderr," DER = %d\n", DegreeOfEdge(p)); } void PrtDOV(Place_t p) { PrintPlace(stderr, p, 5, FALSE); fprintf(stderr," "); fprintf(stderr," DOV = %d\n", DegreeOfNode(p)); } void PrtNextE(Place_t p) { PrintPlace(stderr, p, 5, FALSE); fprintf(stderr, " NextE = "); PrintPlace(stderr, NextE(p), 5, TRUE); } void PrtNextF(Place_t p) { PrintPlace(stderr, p, 5, FALSE); fprintf(stderr, " NextF = "); PrintPlace(stderr, NextF(p), 5, TRUE); } void PrtOrgNum(Place_t p) { PrintPlace(stderr, p, 5, FALSE); fprintf(stderr," OrgV = %d\n", OrgV(p)->num); } void PrtWallNum(Place_t p) { PrintPlace(stderr, p, 5, FALSE); fprintf(stderr, " PWall = %d\n", PWall(p)->num); } void PrtEdgeNum(Place_t p) { PrintPlace(stderr, p, 1, FALSE); fprintf(stderr, " PEdge = %d\n", PEdge(p)->num); } void PrtPnegNum(Place_t p) { PrintPlace(stderr, p, 1, FALSE); if (Pneg(p) != NULL) { fprintf(stderr, " Pneg = %d\n", PnegP(p)->num); } else { fprintf(stderr, " Pneg = NULL\n"); } } void PrtPposNum(Place_t p) { PrintPlace(stderr, p, 1, FALSE); if (Ppos(p)!=NULL) { fprintf(stderr, " Ppos = %d\n", PposP(p)->num); } else { fprintf(stderr, " Ppos = NULL\n"); } } void PrtNextPneg(Place_t p) { auto void PrintPnegsOfWall(Place_t q); void PrintPnegsOfWall(Place_t q) { Place_t h = q; do { PrtPnegNum(h); h = PrevE(h); } while (h != q); } Place_t t = p; PrintPnegsOfWall(t); do { PrintPnegsOfWall(Clock(PrevF(t))); t = PrevE(t); } while (t != p); } void PrtNextPpos(Place_t p) { auto void PrintPposOfWall(Place_t q); void PrintPposOfWall(Place_t q) { Place_t h = q; do { PrtPposNum(h); h = PrevE(h); } while (h != q); } Place_t t = p; PrintPposOfWall(t); do { PrintPposOfWall(Clock(NextF(t))); t = PrevE(t); } while (t != p); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Triangle.c /* See {Triangle.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-25 14:00:41 by stolfi */ #define Triangle_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include Place_t MakeTriangle(void) { Place_t a = MakeWedge(); Place_t b = MakeWedge(); Place_t c = MakeWedge(); Wall_t f = PWall(a); Node_t u = MakeNode(); Node_t v = MakeNode(); Node_t w = MakeNode(); SetOrg(a, u); SetOrg(Clock(a),v); SetNextE(a,b); SetWallInfo(b,f); SetOrg(b,v); SetOrg(Clock(b),w); SetNextE(b,c); SetWallInfo(c,f); SetOrg(c, w); SetOrg(Clock(c), OrgV(a)); return a; } #define Triangle_C_author \ "Created by L. A. P. Lozada, 2000.\n" \ "Modification history:\n" \ " 26-01-2007 Converted to C by J. Stolfi." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Dodecahedron.c /* See {Dodecahedron.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 14:46:01 by stolfi */ #define Dodecahedron_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE SixPlaces_t HalfDodecahedron(void); /* Builds half a dodecahedron. */ Place_t NextE2(Place_t p); /* = NextE(NextE(p)) */ Place_t PrevE2(Place_t p); /* = PrevE(PrevE(p)) */ SixPlaces_t HalfDodecahedron(void) { SixPlaces_t a; int i; for (i = 0; i < 6; i++) { a.p[i] = MakePolygon(5); } SetNextF( a.p[0], Clock(PrevE(a.p[3]))); SetNextF( NextE(a.p[0]), Clock(PrevE(a.p[2]))); SetNextF(NextE2(a.p[0]), Clock(PrevE(a.p[1]))); SetNextF( PrevE(a.p[0]), Clock(PrevE(a.p[4]))); SetNextF(PrevE2(a.p[0]), Clock(PrevE(a.p[5]))); SetNextF(a.p[5], Clock(PrevE2(a.p[1]))); SetNextF(a.p[1], Clock(PrevE2(a.p[2]))); SetNextF(a.p[2], Clock(PrevE2(a.p[3]))); SetNextF(a.p[3], Clock(PrevE2(a.p[4]))); SetNextF(a.p[4], Clock(PrevE2(a.p[5]))); for (i = 0; i < 6; i++) { SetOrgAll( a.p[i], OrgV( a.p[i]) ); SetOrgAll( NextE(a.p[i]), OrgV( NextE(a.p[i]))); SetOrgAll(NextE2(a.p[i]), OrgV(NextE2(a.p[i]))); SetOrgAll( PrevE(a.p[i]), OrgV( PrevE(a.p[i]))); SetOrgAll(PrevE2(a.p[i]), OrgV(PrevE2(a.p[i]))); } return a; } Place_t MakeDodecahedron(void) { SixPlaces_t a = HalfDodecahedron(); SixPlaces_t b = HalfDodecahedron(); SetNextF( NextE(b.p[8-6]), Clock( NextE(a.p[4]))); SetNextF(NextE2(b.p[8-6]), Clock(NextE2(a.p[5]))); SetNextF(NextE2(b.p[9-6]), Clock(NextE2(a.p[4]))); SetNextF( NextE(b.p[9-6]), Clock( NextE(a.p[3]))); SetNextF(NextE2(b.p[10-6]), Clock(NextE2(a.p[3]))); SetNextF( NextE(a.p[2]), Clock( NextE(b.p[10-6]))); SetNextF(NextE2(a.p[2]), Clock(NextE2(b.p[11-6]))); SetNextF( NextE(a.p[1]), Clock( NextE(b.p[11-6]))); SetNextF( NextE(a.p[5]), Clock( NextE(b.p[7-6]))); SetNextF(NextE2(a.p[1]), Clock(NextE2(b.p[7-6]))); int i; for (i = 0; i < 6; i++) { SetOrgAll( a.p[i], OrgV( a.p[i]) ); SetOrgAll( NextE(a.p[i]), OrgV( NextE(a.p[i]))); SetOrgAll(NextE2(a.p[i]), OrgV(NextE2(a.p[i]))); SetOrgAll( PrevE(a.p[i]), OrgV( PrevE(a.p[i]))); SetOrgAll(PrevE2(a.p[i]), OrgV(PrevE2(a.p[i]))); } for (i = 0; i < 6; i++) { SetOrgAll( b.p[i], OrgV( b.p[i]) ); SetOrgAll( NextE(b.p[i]), OrgV( NextE(b.p[i]))); SetOrgAll(NextE2(b.p[i]), OrgV(NextE2(b.p[i]))); SetOrgAll( PrevE(b.p[i]), OrgV( PrevE(b.p[i]))); SetOrgAll(PrevE2(b.p[i]), OrgV(PrevE2(b.p[i]))); } return a.p[0]; } Place_t NextE2(Place_t p) { return NextE(NextE(p)); } Place_t PrevE2(Place_t p) { return PrevE(PrevE(p)); } #define Dodecahedron_C_author \ "Created by L. A. P. Lozada, UNICAMP, 1999-2000. Revisions:\n" \ " 26-01-2007 : Moved {MakeDodecahedron} and {HalfDodecahedron}\n" \ " from {MakePlatonic.c} to here.\n" \ " 24-01-2007 : Converted to C by J. Stolfi // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/TriangulatedDodecahedron.c /* See {TriangulatedDodecahedron.h} */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-27 15:00:34 by stolfi */ #define TriangulatedDodecahedron_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include FiveByTwoPlaces_t BuildPentaPyramid(void); /* Builds a pentagonal bipyramid as the gluing of five tetrahedra. This procedure is a special case of the procedure MakeBipyramid in the module with the same name. */ TwelveByFivePlaces_t TriangulatedDodecahedron2(void) /* [!!! Return type was {Free_vec_t}.] */ { /* Create the 12 pentagonal pyramids, {ap[0..11]}: */ FiveByTwoPlaces_t ap[12]; int i; for (i = 0; i < 12; i++) { ap[i] = BuildPentaPyramid(); } /* Build the first half-dodecahedron, by gluing the pentagonal pyramids: p[0][0][0] <----> p[1][0][0] p[0][1][0] <----> p[2][0][0] p[0][2][0] <----> p[3][0][0] p[0][3][0] <----> p[4][0][0] p[0][4][0] <----> p[5][0][0] */ for (i = 1; i < 6; i++) { Glue(Clock(ap[0].p[i-1][0]), ap[i].p[0][0], 1, TRUE); } Glue(Clock(ap[ 2].p[1][0]), ap[ 1].p[4][0], 1, TRUE); /* p01-p02 */ Glue(Clock(ap[ 3].p[1][0]), ap[ 2].p[4][0], 1, TRUE); /* p02-p03 */ Glue(Clock(ap[ 4].p[1][0]), ap[ 3].p[4][0], 1, TRUE); /* p03-p04 */ Glue(Clock(ap[ 5].p[1][0]), ap[ 4].p[4][0], 1, TRUE); /* p04-p05 */ Glue(Clock(ap[ 1].p[1][0]), ap[ 5].p[4][0], 1, TRUE); /* p05-p01 */ /* Building the second half-dodecahedron, by gluing the pentagonal pyramids: p[ 6][0][0] <----> p[ 7][0][0] p[ 6][1][0] <----> p[ 8][0][0] p[ 6][2][0] <----> p[ 9][0][0] p[ 6][3][0] <----> p[10][0][0] p[ 6][4][0] <----> p[11][0][0] */ for (i = 7; i < 12; i++) { Glue(Clock(ap[6].p[i-7][0]), ap[i].p[0][0], 1, TRUE); } Glue(Clock(ap[ 8].p[1][0]), ap[ 7].p[4][0], 1, TRUE); /* p08-p07 */ Glue(Clock(ap[ 9].p[1][0]), ap[ 8].p[4][0], 1, TRUE); /* p09-p08 */ Glue(Clock(ap[10].p[1][0]), ap[ 9].p[4][0], 1, TRUE); /* p10-p09 */ Glue(Clock(ap[11].p[1][0]), ap[10].p[4][0], 1, TRUE); /* p11-p10 */ Glue(Clock(ap[ 7].p[1][0]), ap[11].p[4][0], 1, TRUE); /* p07-p11 */ /* Gluing the two half dodecahedra */ Glue(Clock(ap[ 7].p[2][0]), ap[1].p[2][0], 1, TRUE); Glue(Clock(ap[ 7].p[3][0]), ap[5].p[3][0], 1, TRUE); Glue(Clock(ap[ 8].p[2][0]), ap[5].p[2][0], 1, TRUE); Glue(Clock(ap[ 8].p[3][0]), ap[4].p[3][0], 1, TRUE); Glue(Clock(ap[ 9].p[2][0]), ap[4].p[2][0], 1, TRUE); Glue(Clock(ap[ 9].p[3][0]), ap[3].p[3][0], 1, TRUE); Glue(Clock(ap[10].p[2][0]), ap[3].p[2][0], 1, TRUE); Glue(Clock(ap[10].p[3][0]), ap[2].p[3][0], 1, TRUE); Glue(Clock(ap[11].p[2][0]), ap[2].p[2][0], 1, TRUE); Glue(Clock(ap[11].p[3][0]), ap[1].p[3][0], 1, TRUE); TwelveByFivePlaces_t fr; int j, k; for (j = 0; j < 12; j++) { for (k = 0; k < 5; k++) { fr.p[j][k] = ap[j].p[k][1]; } } return fr; } FiveByTwoPlaces_t BuildPentaPyramid(void) { /* Create the five tetrahedra */ EightPlaces_t a[5]; int i, j; for (i = 0; i < 5; i++) { a[i] = MakeTetraTopo(1,1); } /* Glue them together: */ for (i = 0; i < 5; i++) { Glue(Spin(a[i].p[1]), a[(i+1) % 5].p[0], 1, TRUE); } /* Emphasize the original elements: */ SetExWallsOfEdge(a[0].p[1], FALSE); for (i = 0; i < 5; i++) { SetExEdge( a[i].p[1], FALSE); SetExEdge(NextE(a[i].p[1]),FALSE); SetExEdge(PrevE(a[i].p[1]),FALSE); SetExWall( a[i].p[3], FALSE); } SetExNode(a[0].p[1], FALSE); SetExNode(Clock(a[0].p[1]), FALSE); /* Gather the places to be returned: */ FiveByTwoPlaces_t p; for (j = 0; j < 5; j++) { p.p[j][0] = a[j].p[3]; p.p[j][1] = a[j].p[2]; } return p; } typedef struct z4_t { int ix[4]; } z4_t; /* A quadruple of integers. */ TwelveByFivePlaces_t MakeTriangulatedDodecahedron(bool_t original) { uint NP = 60; FourPlaces_t tetra[NP]; z4_t cell4[NP]; Place_t walls[4*NP]; z4_t glues[2*NP]; auto Place_t GlueTetras(uint Ti, uint Tj, uint Ci, uint Cj); /* Glues the tetrahedra {tetra[Ti]} and {tetra[Tj]} through the free walls with cell-relative indices {Ci} and {Cj} respectively. */ auto void SetCornersTetra(uint Ti, z4_t row); /* Sets the labels {row} in the tetrahedron with index {Ti}. */ auto void EffaceNode(uint Ti, uint nn); /* Sets node number {nn} of the tetrahedron with index {Ti} as non-existing.*/ auto void EffaceEdgesOfNode(uint Ti, uint nn); /* Sets all edgess incident on node {nn} as non-existing.*/ auto void EffaceWallsOfNode(uint Ti, uint nn); /* Sets all walls incident on node {nn} as non-existing.*/ auto void SaveFreeCorners(void); /* Saves the free corners on the triangulated dodecahedron, so that the result can be used as a building block to assemble other 3D maps. */ auto bool_t MustBeGlued(Place_t Ti, Place_t Tj); /* Return TRUE if the walls {PWall(Ti)} and {PWall(Tj)} have coherent orientations and must be glued. */ uint count = 1; TwelveByFivePlaces_t dode; /* Create the cells {tetra[0..NP-1]}: */ int i, j, k, l, m; for (i = 0; i < NP; i++) { EightPlaces_t poly = MakeTetraTopo(1,1); for (j = 0; j < 4; j++) { tetra[i].p[j] = poly.p[j]; assert(Ppos(tetra[i].p[j]) == NULL); } } /* Set {cell4[i]} to the four indices of corner nodes of {tetra[i]}: */ cell4[ 0] = (z4_t){{100, 500, 0, 1}}; cell4[ 1] = (z4_t){{100, 500, 1, 4}}; cell4[ 2] = (z4_t){{100, 500, 4, 7}}; cell4[ 3] = (z4_t){{100, 500, 7, 2}}; cell4[ 4] = (z4_t){{100, 500, 2, 0}}; cell4[ 5] = (z4_t){{500, 101, 0, 1}}; cell4[ 6] = (z4_t){{500, 101, 1, 5}}; cell4[ 7] = (z4_t){{500, 101, 5, 8}}; cell4[ 8] = (z4_t){{500, 101, 8, 3}}; cell4[ 9] = (z4_t){{500, 101, 3, 0}}; cell4[ 10] = (z4_t){{500, 102, 2, 0}}; cell4[ 11] = (z4_t){{500, 102, 0, 3}}; cell4[ 12] = (z4_t){{500, 102, 3, 9}}; cell4[ 13] = (z4_t){{500, 102, 9, 6}}; cell4[ 14] = (z4_t){{500, 102, 6, 2}}; cell4[ 15] = (z4_t){{103, 500, 6, 2}}; cell4[ 16] = (z4_t){{500, 103, 7, 2}}; cell4[ 17] = (z4_t){{103, 500, 7, 13}}; cell4[ 18] = (z4_t){{103, 500, 13, 12}}; cell4[ 19] = (z4_t){{500, 103, 6, 12}}; cell4[ 20] = (z4_t){{500, 104, 1, 4}}; cell4[ 21] = (z4_t){{500, 104, 4, 10}}; cell4[ 22] = (z4_t){{500, 104, 10, 11}}; cell4[ 23] = (z4_t){{500, 104, 11, 5}}; cell4[ 24] = (z4_t){{500, 104, 5, 1}}; cell4[ 25] = (z4_t){{500, 105, 9, 3}}; cell4[ 26] = (z4_t){{500, 105, 3, 8}}; cell4[ 27] = (z4_t){{500, 105, 8, 14}}; cell4[ 28] = (z4_t){{500, 105, 14, 15}}; cell4[ 29] = (z4_t){{500, 105, 15, 9}}; cell4[ 30] = (z4_t){{500, 106, 12, 6}}; cell4[ 31] = (z4_t){{500, 106, 6, 9}}; cell4[ 32] = (z4_t){{500, 106, 9, 15}}; cell4[ 33] = (z4_t){{500, 106, 15, 18}}; cell4[ 34] = (z4_t){{500, 106, 18, 12}}; cell4[ 35] = (z4_t){{500, 107, 4, 7}}; cell4[ 36] = (z4_t){{500, 107, 7, 13}}; cell4[ 37] = (z4_t){{500, 107, 13, 16}}; cell4[ 38] = (z4_t){{500, 107, 16, 10}}; cell4[ 39] = (z4_t){{500, 107, 10, 4}}; cell4[ 40] = (z4_t){{108, 500, 5, 8}}; cell4[ 41] = (z4_t){{108, 500, 8, 14}}; cell4[ 42] = (z4_t){{108, 500, 14, 17}}; cell4[ 43] = (z4_t){{108, 500, 17, 11}}; cell4[ 44] = (z4_t){{108, 500, 11, 5}}; cell4[ 45] = (z4_t){{109, 500, 18, 12}}; cell4[ 46] = (z4_t){{109, 500, 12, 13}}; cell4[ 47] = (z4_t){{109, 500, 13, 16}}; cell4[ 48] = (z4_t){{109, 500, 16, 19}}; cell4[ 49] = (z4_t){{109, 500, 19, 18}}; cell4[ 50] = (z4_t){{500, 110, 18, 15}}; cell4[ 51] = (z4_t){{500, 110, 15, 14}}; cell4[ 52] = (z4_t){{500, 110, 14, 17}}; cell4[ 53] = (z4_t){{500, 110, 17, 19}}; cell4[ 54] = (z4_t){{500, 110, 19, 18}}; cell4[ 55] = (z4_t){{111, 500, 10, 11}}; cell4[ 56] = (z4_t){{111, 500, 11, 17}}; cell4[ 57] = (z4_t){{111, 500, 17, 19}}; cell4[ 58] = (z4_t){{111, 500, 19, 16}}; cell4[ 59] = (z4_t){{111, 500, 16, 10}}; /* set the labels for each tetrahedra */ for (i = 0; i < NP; i++) { SetCornersTetra(i, cell4[i]); } if (original) { /* Emphasize the original elements */ for (i = 0; i < NP; i++) { EffaceNode(i,500); EffaceEdgesOfNode(i,500); EffaceWallsOfNode(i,500); for (j = 100; j < 112; j++) { EffaceNode(i,j); EffaceEdgesOfNode(i,j); } } } /* Collect the walls of all tetrahedra for gluing: */ for (i = 0; i < NP; i++) { for (k = 0; k < 4; k++) { walls[(4*i)+k] = tetra[i].p[k]; } } /* Figure out which cells must be glued: */ for(k = 0; k < 4*NP; k++) { for (l = k+1; l < 4*NP; l++) { for (m = 0; m < 3; m++) { Place_t e = NextEK(walls[l], m); if (MustBeGlued(walls[k], e)) { uint kc = k % 4; uint kt = k / 4; uint lc = l % 4; uint lt = l / 4; glues[count-1] = (z4_t){{kt, lt, kc, lc}}; count++; } } } } /* Do the automatic gluing of tetrahedra */ for(i = 0; i < 2*NP; i++) { z4_t c = glues[i]; if ((c.ix[0] != 0) || (c.ix[1] != 0) || (c.ix[2] != 0) || (c.ix[3] != 0)) { GlueTetras(c.ix[0],c.ix[1],c.ix[2],c.ix[3]); } } /* Set the origins. */ for (i = 0; i < NP; i++) { for (j = 0; j < 4; j++) { Place_t a = tetra[i].p[j]; Place_t b = NextE(a); Place_t c = PrevE(a); SetOrgAll(a, OrgV(a)); SetOrgAll(b, OrgV(b)); SetOrgAll(c, OrgV(c)); } } SaveFreeCorners(); return dode; /* Implementations of internal procs: */ Place_t GlueTetras(uint Ti, uint Tj, uint Ci, uint Cj) { uint comb = 4*Ci + Cj + 1; switch (comb) { case 1: /* (Ci == 0) && (Cj == 0) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 2: /* (Ci == 0) && (Cj == 1) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 3: /* (Ci == 0) && (Cj == 2) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 4: /* (Ci == 0) && (Cj == 3) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 5: /* (Ci == 1) && (Cj == 0) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 6: /* (Ci == 1) && (Cj == 1) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 7: /* (Ci == 1) && (Cj == 2) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 8: /* (Ci == 1) && (Cj == 3) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 9: /* (Ci == 2) && (Cj == 0) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 10: /* (Ci == 2) && (Cj == 1) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 11: /* (Ci == 2) && (Cj == 2) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 12: /* (Ci == 2) && (Cj == 3) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 13: /* (Ci == 3) && (Cj == 0) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 14: /* (Ci == 3) && (Cj == 1) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 15: /* (Ci == 3) && (Cj == 2) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 16: /* (Ci == 3) && (Cj == 3) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; default: assert(FALSE); } return tetra[Ti].p[0]; } void SetCornersTetra(uint Ti, z4_t row) { Node_t a = OrgV(tetra[Ti].p[0]); Node_t b = OrgV(Clock(tetra[Ti].p[0])); Node_t c = OrgV(PrevE(tetra[Ti].p[1])); Node_t d = OrgV(PrevE(tetra[Ti].p[0])); a->num = row.ix[0]; b->num = row.ix[1]; c->num = row.ix[2]; d->num = row.ix[3]; } void EffaceNode(uint Ti, uint nn) { Node_t a = OrgV(tetra[Ti].p[0]); Node_t b = OrgV(Clock(tetra[Ti].p[0])); Node_t c = OrgV(PrevE(tetra[Ti].p[1])); Node_t d = OrgV(PrevE(tetra[Ti].p[0])); if (a->num == nn) { a->exists = FALSE; } if (b->num == nn) { b->exists = FALSE; } if (c->num == nn) { c->exists = FALSE; } if (d->num == nn) { d->exists = FALSE; } } void EffaceEdgesOfNode(uint Ti, uint nn) { uint a = OrgV(tetra[Ti].p[0])->num; uint b = OrgV(Clock(tetra[Ti].p[0]))->num; uint c = OrgV(PrevE(tetra[Ti].p[1]))->num; uint d = OrgV(PrevE(tetra[Ti].p[0]))->num; Edge_t e0 = PEdge(tetra[Ti].p[0]); Edge_t e1 = PEdge(tetra[Ti].p[2]); Edge_t e2 = PEdge(NextE(tetra[Ti].p[2])); Edge_t e3 = PEdge(PrevE(tetra[Ti].p[2])); Edge_t e4 = PEdge(NextE(tetra[Ti].p[0])); Edge_t e5 = PEdge(NextE(tetra[Ti].p[1])); if ((a == nn) || (b == nn)) { e0->exists = FALSE; } if ((c == nn) || (d == nn)) { e1->exists = FALSE; } if ((a == nn) || (d == nn)) { e2->exists = FALSE; } if ((a == nn) || (c == nn)) { e3->exists = FALSE; } if ((b == nn) || (d == nn)) { e4->exists = FALSE; } if ((b == nn) || (c == nn)) { e5->exists = FALSE; } } void SaveFreeCorners(void) { auto void SaveFreeCornersOfWall(Place_t b, uint i); void SaveFreeCornersOfWall(Place_t b, uint i) { if (SpinBit(b) == 0) { dode.p[i][0] = b; for (j = 1; j < 5; j++) { dode.p[i][j] = Clock(NextE(NextF(PrevE(dode.p[i][j-1])))); } } else { dode.p[i][0] = b; for (j = 1; j < 5; j++) { dode.p[i][j] = Clock(PrevE(NextF(NextE(dode.p[i][j-1])))); } } } uint m = 0; uint n = 0; for (i = 0; i < 60; i++) { for (j = 0; j < 4; j++) { Place_t a = tetra[i].p[j]; uint d = DegreeOfWall(a); if ((d!=1) && (Ppos(a) == NULL)) { dode.p[m][n] = tetra[i].p[j]; n++; if (n == 5){ m++; n = 0; } } } } SaveFreeCornersOfWall(dode.p[0][0],0); dode.p[ 1][0] = Spin(NextF(dode.p[0][0])); SaveFreeCornersOfWall(dode.p[ 1][0], 1); dode.p[ 2][0] = Spin(NextF(dode.p[0][4])); SaveFreeCornersOfWall(dode.p[ 2][0], 2); dode.p[ 3][0] = Spin(NextF(dode.p[0][3])); SaveFreeCornersOfWall(dode.p[ 3][0], 3); dode.p[ 4][0] = Spin(NextF(dode.p[0][2])); SaveFreeCornersOfWall(dode.p[ 4][0], 4); dode.p[ 5][0] = Spin(NextF(dode.p[0][1])); SaveFreeCornersOfWall(dode.p[ 5][0], 5); dode.p[ 8][0] = Spin(NextF(dode.p[4][2])); SaveFreeCornersOfWall(dode.p[ 8][0], 8); dode.p[ 6][0] = Spin(NextF(dode.p[8][3])); SaveFreeCornersOfWall(dode.p[ 6][0], 6); dode.p[ 7][0] = Spin(NextF(dode.p[6][1])); SaveFreeCornersOfWall(dode.p[ 7][0], 7); dode.p[ 9][0] = Spin(NextF(dode.p[6][4])); SaveFreeCornersOfWall(dode.p[ 9][0], 9); dode.p[10][0] = Spin(NextF(dode.p[6][3])); SaveFreeCornersOfWall(dode.p[10][0], 10); dode.p[11][0] = Spin(NextF(dode.p[6][2])); SaveFreeCornersOfWall(dode.p[11][0], 11); /* the free corners are computed follows the scheme bellow: /|\ /|\ / | \ / | \ / | \ / | \ / 3 | 2 \ / 3 | 2 \ / | \ / | \ /-----|-----\ /-----|-----\ \ 4 / \ 1 / \ 4 / \ 1 / \ / 0 \ / \ / 0 \ / \/_____\/ \/_____\/ <--- ---> SpinBit == 0 SpinBit == 1 */ } void EffaceWallsOfNode(uint Ti, uint nn) { uint a = OrgV(tetra[Ti].p[0])->num; uint b = OrgV(Clock(tetra[Ti].p[0]))->num; uint c = OrgV(PrevE(tetra[Ti].p[1]))->num; uint d = OrgV(PrevE(tetra[Ti].p[0]))->num; Wall_t f0 = PWall(tetra[Ti].p[0]); Wall_t f1 = PWall(tetra[Ti].p[1]); Wall_t f2 = PWall(tetra[Ti].p[2]); Wall_t f3 = PWall(tetra[Ti].p[3]); if ((a == nn) || (b == nn) || (d == nn)) { f0->exists = FALSE; } if ((a == nn) || (b == nn) || (c == nn)) { f1->exists = FALSE; } if ((a == nn) || (c == nn) || (d == nn)) { f2->exists = FALSE; } if ((b == nn) || (c == nn) || (d == nn)) { f3->exists = FALSE; } } bool_t MustBeGlued(Place_t Ti, Place_t Tj) { uint ao = OrgV(Ti)->num; uint an = OrgV(NextE(Ti))->num; uint ap = OrgV(PrevE(Ti))->num; uint bo = OrgV(Tj)->num; uint bn = OrgV(NextE(Tj))->num; uint bp = OrgV(PrevE(Tj))->num; return ( ((ao == bo) && (an == bn) && (ap == bp)) || ((ao == bo) && (an == bp) && (ap == bn)) ); } } #define TriangulatedDodecahedron_C_author \ "Modula-3 version created by L. Lozada in 1999-2000. Revisions:\n" \ " 19-09-2000 : Added the procedure {MakeTriangulatedDodecahedron}.\n" \ " 24-01-2007 : Converted to C by J. Stolfi;\n" \ " got {MakeTriangulatedDodecahedron} from {Squared.c}." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakePlatonic.c #define PROG_NAME "MakePlatonic" #define PROG_DESC "" #define PROG_VERS "1.0" #define MakePlatonic_C_COPYRIGHT \ "Copyright © 1999 Universidade Estadual de Campinas (UNICAMP)" #define PROG_HELP \ " "PROG_NAME " \\\n" \ " -shape { icosahedron | dodecahedron } \\\n" \ " [ -output {FILENAME} ]" #define PROG_INFO \ "Builds the platonic solid icosahedron and dodecahedron as unique cell," \ " i.e. without cells information." // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include typedef enum {Shape_Icosahedron, Shape_Dodecahedron} Shape_t; /* [!!!] Rename {Shape_t} */ typedef struct Options_t { char *output; Shape_t shape; char *shapeName; } Options_t; Options_t *GetOptions(int argc, char **argv); Place_t MakeTheShape(Shape_t shape); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s (%s) on %s", PROG_NAME, o->shapeName, today()); /* Random_t coins = MakeRandomSource(4615); */ char *geom_cmt = "\nRandom geometry"; Place_t m = MakeTheShape(o->shape); ElemTableRec_t top = MakeElemTable(Place_vec_desc(&m, 1)); Coords_t c = GenCoords(&top);; /* Set the "root" attribute for walls and edges. */ int i; for (i = 0; i < top.wall.ne; i++) { Wall_t f = PWall(top.wall.e[i]); f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = PEdge(top.edge.e[i]); e->root = e->num; } char *tag = ""; WriteTopology(o->output, tag, &top, topo_cmt); WriteState(o->output, tag, &top, &c, txtcat(topo_cmt, geom_cmt)); WriteMaterials(o->output, tag, &top, topo_cmt, FALSE); return 0; } Place_t MakeTheShape(Shape_t shape) { switch (shape) { case Shape_Icosahedron: { TwentyPlaces_t twp = MakeIcosahedronTriang(FALSE); return twp.p[0]; } case Shape_Dodecahedron: { return MakeDodecahedron(); } default: { assert(FALSE); } } } Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "icosahedron")) { o->shape = Shape_Icosahedron; } else if (0 == strcmp(o->shapeName, "dodecahedron")) { o->shape = Shape_Dodecahedron; } else { argparser_error(pp, "invalid shape"); } argparser_finish(pp); return o; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeElongBip.c #define PROG_NAME "MakeElongBip" #define PROG_DESC "Generates a 3D map which is an elongated bipyramid' #define PROG_VERS "1.0" #define MakeElongBip_C_COPYRIGHT \ "Copyright © 1999 Universidade Estadual de Campinas (UNICAMP)" #define PROG_HELP \ " " PROG_NAME " \\\n" \ " -outName NAME \\\n" \ " -order NUM\n" #define PROG_INFO \ " Generates \".tp\",\".tb\",\".ma\" and \".st\" files for some simple 3D" \ " cells called `elongated bipyramids'. The node coordinates are random" \ " numbers in [-1..+1]." // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include #include typedef struct Options_t { char *outName; uint order; /* Number of tetrahedra per layer. */ } Options_t; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, today()); char *geom_cmt = "\nRandom geometry"; /* Random_t coins = MakeRandomSource(4615); */ fprintf(stderr, "topology: elongated_bipyramid(%d)\n", o->order); Place_t m = MakeElongBip(o->order); ElemTableRec_t top = MakeElemTable(Place_vec_desc(&m,1)); /* [!!! Had extra argument {1} ] */ Coords_t c = GenCoords(&top); /* Set the "root" attribute for walls and edges. */ int i; for (i = 0; i < top.wall.ne; i++) { Wall_t f = PWall(top.wall.e[i]); f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = PEdge(top.edge.e[i]); e->root = e->num; } WriteTopology(o->outName, "", &top, topo_cmt); WriteState(o->outName, "", &top, &c, txtcat(topo_cmt, geom_cmt)); WriteMaterials(o->outName, "", &top, topo_cmt, FALSE); return 0; } Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-outName"); o->outName = argparser_get_next(pp); argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 3, 100); argparser_finish(pp); return o; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeBipyramid.c #define PROG_NAME "MakeBipyramid" #define PROG_DESC "Creates \"bipyramid\" and \"elongated bipyramid\" 3D maps" #define PROG_VERS "1.0" // #TIMESTAMP /* Last edited on DATE TIME by USER */ #define PROG_COPYRIGHT \ "Copyright © 1999,2007 by the State University of Campinas (UNICAMP)" #define PROG_HELP \ " " PROG_NAME " \\\n" \ " -output {NAME} \\\n" \ " -order {NUM} [ -open ] \\\n" \ " [ -fixed [-pyramid] ] \\\n" \ " [ -elongated ]" #define PROG_INFO \ "NAME\n" \ " " PROG_NAME " - " PROG_DESC "\n" \ "\n" \ "SYNOPSIS\n" \ PROG_HELP "\n" \ "\n" \ "DESCRIPTION\n" \ " Generates \".tp\", \".tb\", \".ma\" and \".st\" files for" \ " simple 3D maps called /bipyramids/.\n" \ "\n" \ " A /simple/ bipyramid of order {n} consists of {n} tetrahedral" \ " cells sharing a common edge. With {n == 4} one obtains the" \ " regular octahedron, sliced into four tetrahedra.\n" \ "\n" \ " An /elongated/ bipyramid has a ring of {2*n} triangles" \ " inserted between the two pyramids, shaped as an antiprism" \ " without the top and bottom {n}-gons. With {n == 5}" \ " one obtains the regular icosahedron.\n" \ "\n" \ "OPTIONS\n" \ "\n" \ " -open\n" \ " If this option is present, the last tetrahedron is not glued to the" \ " first one.\n" \ "\n" \ " -fixed\n" \ " If this option is present, the node coordinates are computed" \ " to give a natural shape. Otherwise the node coordinates are set" \ " to random numbers in [-1..+1].\n" \ "\n" \ " -pyramid\n" \ " ???.\n" \ "\n" \ " -elongated\n" \ " ???.\n" \ "\n" \ "DOCUMENTATION OPTIONS\n" \ argparser_help_info_HELP_INFO "\n" \ "\n" \ "SEE ALSO\n" \ " ??? (1).\n" \ "\n" \ "AUTHOR\n" \ " L. A. P. Lozada and J. Stolfi, UNICAMP.\n" \ "\n" \ "MODIFICATION HISTORY\n" \ " 1999 Modula-3 version created by L. A. P. Lozada.\n" \ " 20-05-2000: Emphasized the original elements for drawing purposes.\n" \ " 13-09-2000: Added the option \"pyramid\" for the generation of bipyramids\n" \ " with geometry of pyramids." \ " 24-01-2007 Converted to C and extensively modified by J. Stolfi.\n" \ "\n" \ "WARRANTY\n" \ argparser_help_info_NO_WARRANTY "\n" \ "\n" \ "RIGHTS\n" \ " " PROG_COPYRIGHT ".\n" \ "\n" \ argparser_help_info_STANDARD_RIGHTS // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include #include #include #include typedef struct Options_t { char *output; uint order; bool_t open; bool_t elongated; bool_t fixed; bool_t pyramid; /* Attribute the geometry of a pyramid. */ } Options_t; /* INTERNAL PROTOTYPES */ int main(int argc, char **argv); Options_t *GetOptions(int argc, char** argv); int main(int argc, char **argv) { char *tag; Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, today()); Random_t coins = MakeRandomSource(4615); /* Create the topology (and its description): */ Place_t m; if (o->elongated) { m = BuildElongatedBipyr(o->order); } else { m = BuildSimpleBipyr(o->order, o->open); } /* Make it explicit: */ ElemTableRec_t top = MakeElemTable(Place_vec_desc(&m,1)); /* Set the "root" attribute for walls and edges: */ int i; for (i = 0; i < top.wall.ne; i++) { Wall_t f = PWall(top.wall.e[i]); f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = PEdge(top.edge.e[i]); e->root = e->num; } /* Generate the geometry: */ Coords_t c = r4_vec_new(top.node.ne); char *geom_cmt = NULL; if (! o->fixed) { InitCoords(&coins, &c, 1.0); tag = "-ran"; geom_cmt = "\nRandom Geometry"; } else { demand(! o->open, "Fixed coordinates only allowed for bipyramids"); FixCoordsBipyramid(m, o, top, &c); tag = "-fix"; geom_cmt = "\nBipyramid Geometry"; } /* Output the complex: */ WriteTopology(o->output, tag, &top, topo_cmt); WriteState(o->output, tag, &top, &c, txtcat(topo_cmt, geom_cmt)); WriteMaterials(o->output, tag, &top, topo_cmt, FALSE); fprintf(stderr, "done.\n"); return 0; } Options_t *GetOptions(int argc, char** argv) { /* Initialize argument parser: */ argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); /* Allocate the command line argument record: */ Options_t *o = (Options_t *)malloc(sizeof(Options_t)); /* Parse keyword parameters: */ argparser_get_keyword(pp, "-output"); o->output = argparser_get_next(pp); argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 2,51); o->open = argparser_keyword_present(pp, "-open"); o->fixed = argparser_keyword_present(pp, "-fixed"); o->pyramid = argparser_keyword_present(pp, "-pyramid"); o->elongated = argparser_keyword_present(pp, "-elongated"); argparser_finish(pp); return o; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Minimizer.h #ifndef Minimizer_H #define Minimizer_H /* Multivariate minimization algorithm. */ // #TIMESTAMP /* Last edited on 2007-01-25 02:22:15 by stolfi */ /* [!!! STUB !!!] */ typedef struct MinimizerRec_t *Minimizer_t; #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/ParseMinimizerParams.h #ifndef ParseMinimizerParams_H #define ParseMinimizerParams_H // #TIMESTAMP /* Last edited on 2007-01-25 02:23:12 by stolfi */ #include // #INCLUDE #define parseMinimizerParamsHelp \ " -minimizer [ \\\n" \ " Grad [ RKF4 | Euler ] | \\\n" \ " Coord [ Brent | JS ] [ budget ] \\\n" \ " ]" Minimizer_t ParseMinimizerParams(argparser_t *pp); /* Parses an optimization method from the command line parameters. Returns it still uninitialized. The syntax is described by the {Help} string above. Returns NULL if no "-minimizer" keyword was specified. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Energy.h #ifndef Energy_H #define Energy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE #include /* A generic energy function. */ typedef r4_vec_t Gradient; /* A vector of energy gradients per knot */ typedef struct EnergyRec_t *Energy_t; typedef struct EnergyMethods_t { void (*defTop)(Energy_t self, ElemTableRec_t *top); /* Attaches the energy evaluator {eval} (bellow) to some topological triangulation.Must be called at least once before {defVar} below. */ void (*defVar}(Energy_t self, bool_vec_t *variable); /* Tells {eval} (below) which knots {v} should be considered variables ({variable[v]==TRUE}) or fixed parameters ({variable[v]==FALSE}); see below. Must be called at least once before the first use of {eval}. Since it may be an expensive operation, clients should avoid calling it if the variable knot set hasn't changed. */ void (*eval)(Energy_t self, Coords_t *c, double *e, bool_t grad, Gradient *eDc); /* Returns in {*e} the energy of the attached triangulation when the knots have the coordinates {c}. Also, if {grad} is TRUE, {eval} will store in {*eDc} the gradient of {e}, that is, the partial derivatives of {e} relative to each element of {c}. An {Energy.T} object is typically used inside optimization loops where only some knots are being adjusted, while the others are kept fixed. In that context the absolute value of the energy is not important; only energy differences are important. Accordingly, the {eval} method is free to omit any terms of the energy formula that depend only on fixed knots. (However, the decision to omit a term must not depend on {c}.) The client should be aware that if knot {v} is fixed, the corresponding component of the gradient {eDc[v]} may not be set by {evalGrad}, and therefore should not be used. */ char * (*name)(Energy_t self); /* Prints a description of the energy function. */ } EnergyMethods_t; typedef struct EnergyRec_t { EnergyMethods_t *m; /* Methods vector. */ char *typecode; /* String that identifies the actual allocation type. */ } EnergyRec_t; #define Energy_TYPE "Energy." /* The {typecode} of an {Energy_t} object must begin with this. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/CmpAreaEnergy.h #ifndef CmpAreaEnergy_H #define CmpAreaEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct CmpAreaEnergy_data_t { double area; } CmpAreaEnergy_data_t; /* The "Compression Area" energy measures the discrepancy between the "current" area of one triangular wall of triangulation and the their reference {area}. */ Energy_t CmpAreaEnergy_new(double area); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/CmpVolEnergy.h #ifndef CmpVolEnergy_H #define CmpVolEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct CmpVolEnergy_data_t { double volume; } CmpVolEnergy_data_t; /* The "Compression Volume" energy measures the discrepancy between the "current" volume of one tetrahedron of triangulation and the their "referencial" volume. This last may be associated to volume of one regular tetraedron of side lenght {length}, or simply the "average" volume of triangulation. */ Energy_t CmpVolEnergy_new(double volume); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/CoherentEnergy.h #ifndef CoherentEnergy_H #define CoherentEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ #include // #INCLUDE typedef struct CoherentEnergy_data_t { r4_t From4, To4, Up4, Over4; } CoherentEnergy_data_t; /* The "Coherent" energy try that the tetrahedra {v0,v1,v2,v3} and {u0,u1,u2,u3} have coherent orientations, i.e. that and have the same parity.This requirement can be reaches forcing that their determinants have the same sign. */ Energy_t CoherentEnergy_new(r4_t From4, r4_t To4, r4_t Up4, r4_t Over4); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Curvature1D.h #ifndef Curvature1D_H #define Curvature1D_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct Curvature1D_data_t { } Curvature1D_data_t; /* The {Curvature 1D} energy measures the outer dihedral angles between adjacent @{edge->?}s. This energy is computed only for @{edge->?}s that: - exist, - belong to the same original edges, and - are adjacent to one common knot. The energy depends on the actual angle {A}, as {1 + cos(A)}; which reaches its minimum when {A==Pi}. Let the edges e1 == (u,v), e2 == (u,w) and A the dihedral angle between e1 and e2: v w \ / \ A / \ / \/ u */ Energy_t Curvature1D_new(void); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Curvature2D.h #ifndef Curvature2D_H #define Curvature2D_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct Curvature2D_data_t { } Curvature2D_data_t; /* The {Curvature 2D} energy measures the outer dihedral angles between adjacent walls. This energy is computed only for walls that: - exist, - belong to the same original wall, and - are adjacent to one common @{edge->?}. The energy depends on the actual angle {A}, as {1 + cos(A)}; which reaches its minimum when {A==Pi}. */ Energy_t Curvature2D_new(void); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Curvature3D.h #ifndef Curvature3D_H #define Curvature3D_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct Curvature3D_data_t { } Curvature3D_data_t; /* Ideally, the 3-manifold realized as $\phi(\CT)$ should be as smooth as possible. Each tetrahedron of $\phi({\CT})$ is contained in some 3-di\-men\-sio\ -nal affine subspace of $\Real^m$. In general, if $t_1,t_2$ are two ad- jacent tetrahedra, their images $\phi(t_1)$ and $\phi(t_2)$ will lie in two distinct 3D spaces $V_1,V_2$ of $\Real^{m}$, whose intersection is the plane containing the shared wall $f$. In order to flatten out the mo- del $\phi(\CT)$ at that spot, we need to minimize the angle $\theta_f$ between $V_1$ and $V_2$. This requirement is captured by the {\em curvatu- re energy}, defined as \begin{equation} \Ecurv == \sum_{f \in \WALL{\CT}} \left(1+\cos\theta_{f}\right) \label{eq.curvature} \end{equation} \noindent Note that $1-\cos\theta_{f}$ is approximately $\frac{1}{2} \,\theta_{f}^{2}$ when $\theta_{f}$ is small. Therefore, minimizing $\Ecurv$ tends to make the angles $\theta_{f}$ as small as possible. The value of $\cos \hspace{0.10cm} \theta_{f}$ can be computed by the formula $\cos \theta_f == - r_1 \dotpr r_2/(\abs{r_1}\,\abs{r_2})$, where $r_i$ is a vector in $U_i$ perpendicular to the wall $f$, and pointing into the tetrahe- dron $t_i$, for $i==1,2$. */ Energy_t Curvature3D_new(void); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ElasticityEnergy.h #ifndef ElasticityEnergy_H #define ElasticityEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct ElasticityEnergy_data_t { double alpha; /* the two elastic moduli of the material, that*/ double beta; /* express its resistance to changes in volume */ } ElasticityEnergy_data_t; /* The {Elasticity} energy considers that every tetrahedral chip is done of any material like rubber (i.e. elastic) possesing property material uniformes inside of every tetrahedron, but with unequal propiertes between tetrahedra. This module compute the "elastic energy" of a tetrahedral element. See the section 4.2 "Calculo das forcas de elasticidade" in the Msc. Thesis "Animacao Dinamica de Corpos Elasticos" by R.L.W.L for more details. */ Energy_t ElasticityEnergy_new(double alpha, double beta); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/EquaAngleEnergy.h #ifndef EquaAngleEnergy_H #define EquaAngleEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct EquaAngleEnergy_data_t { } EquaAngleEnergy_data_t; /* The {Equalization Angle} energy measures the non-uniformity of diedral angles among consecutive walls incident to an internal @{edge->?} {e}. We say that an @{edge->?} {e} is internal if every wall incident to {e} is an inter- nal wall. Analosgously, we say that a wall {f} is internal if there exists exactely two tetrahedra incident to it. This energy is computed only for @{edge->?}s that exist, are internal, have wall ring degree (DRF) three or more, and have only existing walls and knots incident to it. The diedral angles not need projected. For two walls consecutives incidents to same @{edge->?}, the ideal angle {I} is {2*Pi/n} where {n} is the wall ring degree correspondly to @{edge->?} {e}. Minimizing this energy tends to equalize the angles between consecutive walls incident to @{edge->?} {e}. f2 \ /f1 \ / \/ e /\ / \ / \ f3 f4 */ Energy_t EquaAngleEnergy_new(void); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ExcenEnergy.h #ifndef ExcenEnergy_H #define ExcenEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct ExcenEnergy_data_t { } ExcenEnergy_data_t; /* The {Excen} energy measures the excentricity (discrepancy) of each knot relative to its immediat neighbors. It is the sum over every existing knot {v} of the distance squared between {v} and the bary- center of the effective neighbors of {v}. An 'effective neighbor' of {v} is a knot that exists and is connected to {v} by an @{edge->?} that exists. Minimizing this energy tends to equalize the edges lengths. */ Energy_t ExcenEnergy_new(void); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Heuristic.h #ifndef Heuristic_H #define Heuristic_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ /* One complex-3D heuristic. */ // #INCLUDE // #INCLUDE void DisplaceKnot(Octf_Place_t p, Coords_t *c, bool_vec_t *variable, ElemTableRec_t *top, rand_t *coins); /* Displace the knot {u==Org(a)}, to neighbor's barycenter so as to minimize the Excentricity energy. Only moves knots that are marked {variable}. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Heuristics.h #ifndef Heuristics_H #define Heuristics_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ /* A couple of complex-3D-regularization heuristics. */ // #INCLUDE // #INCLUDE void EquaAngle(Place_t p, Coords_t *c, bool_vec_t *variable, ElemTableRec_t *top); /* Move the neighbors of {u==Org(a)}, so as to equalize the diedral angles between walls incidents to @{edge->?} {u v} with {v==Org(Clock(a))}. Only moves knots that are marked {variable}. */ void FlattenKnot(Place_t p, Coords_t *c, bool_vec_t *variable, rand_t *coins); /* [COMMENTED OUT IN THE M3 SOURCE !!!] Positions {v==Org(a)} at the barycenter of its neighbors, displaced along the normal by an amount that hopefully minimizes the bending energy between the walls incident to {v} and the walls adjacent to them. A no-op if {v} is not marked variable. */ */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/HingeEnergy.h #ifndef HingeEnergy_H #define HingeEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ /* NOT USED */ // #INCLUDE typedef struct HingeEnergy_data_t { } HingeEnergy_data_t; /* The {Hinge} energy measures the difference among the {ideal} diedral angle and the {average} diedral angle of adjacent walls incident to one @{edge->?}. This energy is computed only for @{edge->?}s that exists, have DegreeRingWalls three or more, and have only existing walls and knots incident to them, and have the {hinge} bit set. Minimizing this energy tends to equalize the diedral angles between adja- cent walls incidents to same @{edge->?}, thus tends to regular configurations. This energy is minimum (zero) when the {ideal} diedral angle is equal to {average} diedral angle between adjacent walls. */ Energy_t HingeEnergy_new(void); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/MixedEnergy.h #ifndef MixedEnergy_H #define MixedEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct MixedEnergy_data_t { Energy_vec_t term; /* Energy ingredients */ double_vec_t weight; /* Weight of each ingredient */ double_vec_t termValue; /* Value of each term as of last {eval}, or empty vec */ } MixedEnergy_data_t; /* A {MixedEnergy.T} is a linear combinations of the energy functions {term[k]}, with weights {weight[k]}. The {eval} method will leave the (unweighted) energy terms in {termValue}. Energy_t MixedEnergy_new(Energy_vec_t *term, double_vec_t *weight); /* Allocates new arrays for {term}, {weight}, and {termValue}, and copies the given arrays into them. Assumes the {term[k]} has been initialized. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ModKamSpring.h #ifndef ModKamSpring_H #define ModKamSpring_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct ModKamSpring_data_t { double length; /* desirable length of a single @{edge->?} in the display plane */ double strength; /* a constant */ } ModKamSpring_data_t; Energy_t ModKamSpring_new(void); /* Kamada's version has a spring between every @place of knots u,v adjacents or not; whose length is equal to the graph-theoretical distance between u and v in T. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/OriKamSpring.h #ifndef OriKamSpring_H #define OriKamSpring_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct OriKamSpring_data_t { double length; /* desirable length of a single @{edge->?} in the display plane */ double strength; /* a constant */ bool_t detail; /* for printing detail information */ } OriKamSpring_data_t; Energy_t OriKamSpring_new(void); /* Kamada's version has a spring between every @place of knots u,v adjacents or not; whose length is equal to the graph-theoretical distance between u and v in T. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/OrientationEnergy.h #ifndef OrientationEnergy_H #define OrientationEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct OrientationEnergy_data_t { double minvol; /* Minimum tetrahedron volume */ } OrientationEnergy_data_t; Energy_t OrientationEnergy_new(void); /* The {Orientation} energy penalizes tetrahedra with negative orientation in R^{3}. This is, for each tetrahedron with extremus knots numbers u,v,w,x compute us theirs projections in R^{3} by dropping the last coordinate. This energy is zero when the tetrahedra have positive volumes greater than minVol */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ParseEnergyParams.h #ifndef ParseEnergyParams_H #define ParseEnergyParams_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ #include // #INCLUDE #define parseEnergyHelp \ " [ -energy Excen ] \\\n" \ " [ -energy Spring \\\n" \ " [ OriKamada [ length | strength | detail ] |\\\n" \ " [ ModKamada [ length | strength ] | \\\n" \ " [ VarKamada [ length | strength ] | \\\n" \ " [ Simple [ length ] ] \\\n" \ " ] \\\n" \ " [ -energy Curv1D ] \\\n" \ " [ -energy Curv2D ] \\\n" \ " [ -energy OldCurv2D ] \\\n" \ " [ -energy Curv3D ] \\\n" \ " [ -energy Orient [ minVol ] ] \\\n" \ " [ -energy Winding ]" /* " [ -energy Spread ] \\\n" \ " [ -energy ComprVol ] \\\n" \ " [ -energy Elasticity] \\\n" */ #define parseEnergyParamsHelp \ " [ -From4 ] \\\n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ] \\\n" \ " [ -density ] \\\n" \ " [ -alpha ] \\\n" \ " [ -beta ] \n" #define parseEnergyOrientHelp \ " [ -From4 ] \\\n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ]\n" Energy_t ParseEnergyParams(argparser_t *pp); /* Parses an energy combination from the command line parameters, returns a {MixedEnergy_t} object. The syntax is as shown in the {Help} string above. If no terms are specified in the command line, returns NULL. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/PartialSpring.h #ifndef PartialSpring_H #define PartialSpring_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct PartialSpring_data_t { double length; /* desirable length of a single @{edge->?} in the display plane */ double strength; /* a constant */ } PartialSpring_data_t; Energy_t PartialSpring_new(void); /* Kamada's version has a spring between every @place of knots u,v adjacents or not; whose length is equal to the graph-theoretical distance between u and v in T. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ProxTetraEnergy.h #ifndef ProxTetraEnergy_H #define ProxTetraEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct ProxTetraEnergy_data_t { double fuzz; /* Relative charge radius, set by user */ } ProxTetraEnergy_data_t; Energy_t ProxTetraEnergy_new(void); /* This energy can be understood as the eletrostatic potential of a set of fuzzy electric charges, located at the tetrahedron centroids. Minimizing this energy tends to spread out the tetrahedrons in the R^{4} space, thus avoiding intersections between tetrahedra. The radius of the charge cloud is {fuzz} times the tetrahedron's approximate radius. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/SimpleSpring.h #ifndef SimpleSpring_H #define SimpleSpring_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct SimpleSpring_data_t { double length; /* desirable length of a single @{edge->?} in the display plane */ } SimpleSpring_data_t; Energy_t SimpleSpring_new(void); /* The {spring} energy is computing assuming that every @{edge->?} is a one elasticity wire that to pull or to push the extremal knots with tension that depend of discrepancy between the "current" length of @{edge->?} and their "referencial" or "nominal" length. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/SpreadEnergy.h #ifndef SpreadEnergy_H #define SpreadEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct SpreadEnergy_data_t { } SpreadEnergy_data_t; Energy_t SpreadEnergy_new(void); /* The {Spread} energy measures the overall spread of the knots. It is the sum over every {existing} and {variable} knot {v} of the distance squared between {v} and the origin. Minimizing this energy tends to keep all knots close to the origin of R^{4}. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/UneqVolEnergy.h #ifndef UneqVolEnergy_H #define UneqVolEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ /* NOT USED */ // #INCLUDE typedef struct UneqVolEnergy_data_t { double area; } UneqVolEnergy_data_t; /* The {Unequal} energy measures the discrepancy between the volume of two tetrahedrons incident to every wall relevant of Triangulation. */ Energy_t UneqVolEnergy_new(double area); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/VarKamSpring.h #ifndef VarKamSpring_H #define VarKamSpring_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct VarKamSpring_data_t { double length; /* desirable length of a single @{edge->?} in the display plane */ double strength; /* a constant */ } VarKamSpring_data_t; Energy_t VarKamSpring_new(void); /* In Kamada's energy, a spring is attached between every @place of triangulation nodes u, v, adjacent or not, whose length is equal to the graph-theoretical distance between u and v in T. In this version, the distances are computed by setting each @{edge->?}'s length to {length * sqrt (Na/Nb + Nb/Na)} where {Na} and {Nb} are the endpoint degrees. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/VarWindingEnergy.h #ifndef VarWindingEnergy_H #define VarWindingEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef enum { VWE_Perimeter, VWE_Area } VarWindingEnergyKind_t; typedef struct VarWindingEnergy_data_t { VarWindingEnergyKind_t kind; /* Kind ??? */ } VarWindingEnergy_data_t; Energy_t VarWindingEnergy_new(void); /* The {VarWinding} energy penalizes @{edge->?}s whose star, when projected to {R^3}, is too irregular, or does not make a single complete turn around the edge's line. The projection to R^3 is performed by dropping the last coordinate. Let {e} be an @{edge->?} with endpoints {u,v}, and let {w[i]} (for {i} in {0..N-1}) be the third corner of the {i}th triangle incident to {e}, in topological order. Let {L} be the line supporting {e}, and {P} be a plane orthogonal to {L}. Define {h == v - u}, {r[i] == h × (w[i] - u)}. Note that {|r[i]|} is the distance from {w[i]} to the line {L} (projected onto the plane {P}), times {|h|}. Define also {R == sum{ |r[i]|^2 }/RNorm}, where {RNorm} is a normalization factor that depends only on the local topology (see below). For the {Perimeter} formula, we define also {s[i] == h × (w[i] - w[i-1])}, and {S == sum{ |s[i]|^2 }/SNorm}, where {SNorm} is a normalization factor. Note that {|s[i]|} is the length of the edge {w[i] - w[i-1]}, projected onto {P} and scaled by {|h|}. For the {Area} formula, we define instead {s[i] == ((r[i] × r[i-1])}, and {S == sum{ s[i] }/SNorm}, where {SNorm} is a (different) normalization factor. Note that {s[i]} here is the signed area of the triangle {u,w[i-1],w[i]}, projected onto {P}, scaled by {|h|^2}, and multiplied by the direction of {h}; so that {S} is the area of the polygon {w[0],.. w[N-1]}, also projected onto {P} and scaled by {|h|^2}. In either case, the energy contributed by @{edge->?} {e} is {(S/R + R/S)^2 - 4}. This formula has minimum value (zero) when {|R| == |S|}, and tends to infinity when {|R/S| -> 0} or {|S/R| -> 0}. The normalization factors {RNorm} and {SNorm} are chosen so that {R,S,T} have the same value when the {w[i]}, projected onto {P}, have an ideal configuration around the line {L}. If {e} is an interior @{edge->?}, the ideal configuration is a regular {N}-gon of arbitrary radius centered on the edge. If {e} lies on the manifold's boundary, and there are {G} gaps (missing cells) in the ring of elements surrounding {e}, then the ideal configuration is a regular {2(N-G)}-gon, consisting of {N-G} `filled' sectors (corresponding to the non-missing cells) and {N-G} `empty' ones (corresponding to missing cells, or fractions thereof). The normalization factors are, therefore | RNorm == In either case, the quantities {R} and {S} will have the same value {b^2|h|^2} In the {Perimeter} formula, . In the {Area} formula, the energy contributed to {e} is {T/R + R/T - 2}. Note that both formulas are not affected by changes of scale in the {r[i]} or {h}. The above defintions assume that {e} is an interior @{edge->?}. If {e} lies on the manifold's border, the {S} and {T} sums ignore the `gaps' (@places {w[i], w[i-1]} that are separated by a null cell). In that case, the factors {SNorm,TNorm} are chosen to give {S == T == b^2|h|^2} when the {w[i]} are {N} corners of a regular {2(N-G)}-gon, where {G} is the number of gaps. */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/WindingEnergy.h #ifndef WindingEnergy_H #define WindingEnergy_H // #TIMESTAMP /* Last edited on DATE TIME by USER */ // #INCLUDE typedef struct WindingEnergy_data_t { } WindingEnergy_data_t; Energy_t VarWindingEnergy_new(void); /* The {Winding} energy penalizes @{edge->?}s whose star, when projected to {R^3}, is too irregular, or does not make a single complete turn around the edge's line. The projection to R^3 is performed by dropping the last coordinate. Let {e} be an @{edge->?} with endpoints {u,v}, and let {w[i]} (for {i} in {0..N-1}) be the third corner of the {i}th triangle incident to {e}, in topological order. Let {L} be the line supporting {e}, and {P} be a plane orthogonal to {L}. Define {h == v - u}, {r[i] == h × (w[i] - u)}. Note that {|r[i]|} is the distance from {w[i]} to the line {L} (projected onto the plane {P}), times {|h|}. Define also {R == sum{ |r[i]|^2 }/RNorm}, where {RNorm} is a normalization factor that depends only on the local topology (see below). Note that, for a fixed topology, {R} is proportional to the mean squared distance of the points {w[i]} to the line {L}, times {|h|^2} Define furthermore {s[i] == h × (w[i] - w[i-1])}, and {S == sum { |s[i]|^2 }/SNorm}, where {SNorm} is a normalization factor. Note that {|s[i]|} is the length of the edge {w[i] - w[i-1]}, projected onto {P} and scaled by {|h|}. Thus, for a fixed topology, {S} is proportional to the mean squared length of the sides of the polygon {w[0..N-1]}, projected onto {P}, times {|h|^2}. The energy contributed by @{edge->?} {e} is then defined as {S/R + R/S - 2}. This formula has minimum value (zero) when {R == S}, and tends to infinity when {R/S -> 0} or {S/R -> 0}. Note, furthermore, that this energy is invariant with respect to the length of the edge {e}, to arbitrary displacement of the {w[i]} parallel to {L}, and to uniform scaling of the configuration. The normalization factors {RNorm} and {SNorm} are chosen so that {R} and {S} have the same value when the {w[i]}, projected onto {P}, have an ideal configuration around the line {L}. If {e} is an interior @{edge->?}, the ideal configuration is a regular {N}-gon of arbitrary radius centered on the edge. The normalization factors are then | RNorm == N | SNorm == 4·N·(sin(Pi/N))^2 If {e} lies on the manifold's boundary, and there are {G} gaps (missing cells) in the ring of elements surrounding {e}, then the ideal configuration is a regular {2(N-G)}-gon, consisting of {N-G} `filled' sectors (corresponding to the non-missing cells) and {N-G} `empty' ones (corresponding to missing cells, or fractions thereof). The normalization factors are then | RNorm == N | SNorm == 4·(N-G)·(sin(Pi/2/(N-G)))^2 */ #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeBigCubeFixed.c /* See {MakeBigCubeFixed.h} */ /* Create a tridimensional array of cubic cells with fixed geometry. */ // #TIMESTAMP /* Last edited on 2007-01-25 14:53:49 by stolfi */ // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include typedef struct Options_t { uint gridOrder; /* order of the grid. */ bool_t original; /* emphazise the original elements on a cube. */ } Options_t; @PLACES == ARRAY[0..3] OF Place_t; double TriPlace_t = ARRAY OF ARRAY OF ARRAY [0..1] OF Place_t; Place_t MakeBigRawCube(uint order, bool_t original) { Place_vec_t cd = BuildBigrawCube(order); TwoPlaces_vec_t a = TwoPlaces_vec_new(order*order); if (original) { /* Selecting the places for emphasize */ for (j = 0; j < order; j++) { for (k = 0; k < order; k++) { a.e[j,k,0] = cd.e[0,k,j,0]; a.e[j,k,1] = cd.e[order-1,k,j,1]; } } } /* Fix the coordinates */ ElemTableRec_t top = MakeElemTable(cd.e[0].p[0]); Coords_t c = r4_vec_new(top->node.ne); double zero = 0.0, one = 1.0; char *cmt = " "; name = "Bigcube-" & Fmt.Int(order); void SetCorner(e: Place_t; uint i) { ??? ii = FLOAT(i, double)); with( double cv = (r4_t){ii,zero,zero,zero} ){ c[OrgV(e)->num] = cv; } } SetCorner; void SetCorner1(e: Place_t; o: r4_t) { c[OrgV(e)->num] = (r4_t){o[0], o[1]+one, o[2], o[3]}; } SetCorner1; void SetCorner2(e: Place_t; o: r4_t) { c[OrgV(e)->num] = (r4_t){o[0], o[1], o[2]+one, o[3]}; } SetCorner2; void SetCorner3(e: Place_t; o: r4_t) { c[OrgV(e)->num] = (r4_t){o[0], o[1]-one, o[2], o[3]}; } SetCorner3; Place_t *p; { for (i = 0; i < order; i++) { SetCorner(Clock(NextE(cd[i,0,0,0])),i); for (j = 0; j < order; j++) { p = Clock(NextE(cd[i,j,0,0])); for (k = 0; k < order; k++) { SetCorner1(NextE(p),c[OrgV(p)->num]); SetCorner2(NextE(NextE(p)),c[OrgV(NextE(p))->num]); SetCorner3(NextE(NextE(NextE(p))),c[OrgV(NextE(NextE(p)))->num]); p = NextE(PrevF(PrevF(cd[i,j,k,0]))); } } } /* finally */ SetCorner(PrevE(cd[order-1,0,0,1]),order); for (j = 0; j < order; j++) { p = PrevE(cd[order-1,j,0,1]); for (k = 0; k < order; k++) { SetCorner1(NextE(p),c[OrgV(p)->num]); SetCorner2(NextE(NextE(p)),c[OrgV(NextE(p))->num]); SetCorner3(NextE(NextE(NextE(p))),c[OrgV(NextE(NextE(p)))->num]); p = Clock(PrevE(NextF(cd[order-1,j,k,1]))); } } if (original) { /* Set all elements (nodes, @{edge->?}s, walls, as non-existing */ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { f->exists = FALSE; } } for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { e->exists = FALSE; } } for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { v->exists = FALSE; } } /* Now emphasize the original elements (nodes,@{edge->?}s,walls) */ SetCubeProperties(a, order, top); name = name; } /* set the root elements */ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { f->root = f->num; } } for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { e->root = e->num; } } WriteTopology(name,top); WriteState(name, top, c, cmt); WriteMaterials(name, top, cmt); return cd[0,0,0,0]; } } } /* END MakeBigRawCube */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-gridOrder"); o->gridOrder = argparser_get_next_int(pp, 1,10); o->original = argparser_keyword_present(pp, "-original"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeRawCube -gridOrder \\\n" \ " [ -original] \n"); END¦ } } return o; } /* END GetOptions */ PROCEDURE Main() Place_t *a; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ { a = MakeBigRawCube(o->gridOrder, o->original); } } /* END Main */ { Main(); } MakeBigCubeFixed. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeComplex.c #define PROG_NAME "MakeComplex" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeComplex_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program generates ".tp",".tb",".st" and ".ma" files for some simples tridimensional maps homeomorphics to three-manifolds. The node coordinates are random numbers in [-1..+1]. The maps builds through the "MakeComplex" program results in dege- neracies. So, is necessary submit these resulting maps to aditional procedures for remove such degeneracies, such as the "BarySubdivision" and "SelectSubdivision" procedures. Revisions: 28-09-2000: Added the 3D maps `Dodecahedral Seifert-Weber' and `Poincare Space'. This maps have topology of closed 3D manifolds and aren't homemorphic to the hypersphere S^{3}. */ // #INCLUDE // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE #include CONST double Order = 1; TYPE Shape_t == { Sphere, Cm2t, Torus, Pseudo, Seifert, Poincare, Lens1, Lens2, Lens3, Lens4, Lens5 }; typedef struct Options_t { shape: Shape_t; shapeName: char *; } Penta == ARRAY [0..4] OF ARRAY [0..1] OF Place_t; Free == ARRAY [0..4] OF Place_t; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakeMap(o->shape); ??? top = MakeElemTable(m; with (0), double c = GenCoords(t)^ ){ /* Set the root elements for edges and walls */ for (i = 0; i < top.wall.ne; i++) { Wall_t f = top.wall.e[i]; f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = top.edge.e[i]; e->root = e->num; } WriteTopology(o->output, tag, &top, topo_cmt); // shapeName MakeComplex shapeName WriteTable(o->output, tag, &top, topo_cmt); // shapeName MakeComplex shapeName WriteState( o->shapeName, top, c, "Created by MakeComplex: " & o->shapeName & ".st on " & Today() & "\nRandom Geometry"); /*Triangulation.FindDegeneracies(top);*/ WriteMaterials(o->output, tag, &top, topo_cmt); // shapeName MakeComplex shapeName return 0; } Place_t MakeMap(Shape_t shape) { CASE shape OF break; case Shape_Sphere: return MakeSphere(); break; case Shape_Cm2t: return MakeCm2t(); break; case Shape_Torus: return MakeTorus(); break; case Shape_Pseudo: return MakePseudo(); break; case Shape_Seifert: return MakeSeifert(); break; case Shape_Poincare: return MakePoincare(); break; case Shape_Lens1: return MakeLens1(); break; case Shape_Lens2: return MakeLens2(); break; case Shape_Lens3: return MakeLens3(); break; case Shape_Lens4: return MakeLens4(); break; case Shape_Lens5: return MakeLens5(); } } /* END MakeMap */ Place_t MakeTorus() { ??? a = MakeBigCube(Order); { GlueBigCube(Clock(Spin(PrevF(a[Order-1,0,0]))), Spin(PrevF(PrevE(PrevE(a[0,0,0])))), Order); GlueBigCube(Spin(a[Order-1,0,1]), Clock(Spin(a[Order-1,0,0])),Order); GlueBigCube(Spin(NextF(PrevE(a[0,0,1]))), Clock(Spin(NextF(NextE(a[0,Order-1,1])))), Order); fprintf(stderr, "Building topology of Torus: \n"); /* Return one @place not kill by the GlueBigCube procedure */ return a[0,0,1]; } } /* END MakeTorus */ Place_t MakeSphere() { ??? a = MakeTetraTopo(Order; with (Order) ){ Glue(Spin(a[1]),a[0],Order); Glue(Spin(a[3]),a[2],Order); fprintf(stderr, "Building topology of Sphere: \n"); /* Return one @place not kill by the Glue Procedure */ return a[1]; } } /* END MakeSphere */ /* UNUSED */ Place_t MakeSphere_H1() { ??? a = MakeTetraTopo(Order; with (Order) ){ Glue(Spin(a[5]),a[4],Order); Glue(Spin(a[7]),a[6],Order); fprintf(stderr, "Building topology of Sphere-h1: \n"); /* Return one @place not kill by the Glue Procedure */ return a[5]; } } /* END MakeSphere_H1 */ /* UNUSED */ Place_t MakeSphere_H2() { ??? a = MakeTetraTopo(Order; with (Order) ){ Glue(Spin(a[1]),a[0],Order); Glue(Spin(a[7]),a[6],Order); fprintf(stderr, "Building topology of Sphere-h2: \n"); /* Return one @place not kill by the Glue Procedure */ return a[1]; } } /* END MakeSphere_H2 */ /* UNUSED */ Place_t MakeSphere_H3() { ??? a = MakeTetraTopo(Order; with (Order) ){ Glue(Spin(a[5]),a[4],Order); Glue(Spin(a[3]),a[2],Order); fprintf(stderr, "Building topology of Sphere-h3: \n"); /* Return one @place not kill by the Glue Procedure */ return a[5]; } } /* END MakeSphere_H3 */ Place_t MakeCm2t() { ??? a = MakeTetraTopo(Order; with (Order), double b = MakeTetraTopo(Order,Order) ){ Glue(Spin(a[1]),b[0],Order); Glue(Spin(a[3]),a[2],Order); Glue(Spin(b[1]),a[0],Order); Glue(Spin(b[3]),b[2],Order); fprintf(stderr, "Building topology of Cm2t: \n"); /* Return one @place not kill by the Glue Procedure */ return Spin(a[3]); } } /* END MakeCm2t */ Place_t MakePoincare() /* This procedure builds the 3-map so called as: "Poincare Dodecahedral Space", generated by gluing @places of opposite wall of a triangulated dodecahedron, when one menber of each @place is matched to its conter- part after a rotation of one-tenth of a turn == PI/5. Equal to the Lens1 procedure below. I believe that still persist one bug !!!. Since the map must be have: double nv = 12 and ne == 72 and not nv == 13 and ne == 73 !!!. */ { ??? d = TriangulatedDodecahedron2(); { /* the opposite walls are: d[0] d[6] d[1] d[9] d[2] d[8] d[3] d[7] d[4] d[11] d[5] d[10] */ EVAL Glue(Clock(d[0][0]), d[6][0],1); EVAL Glue(Clock(d[0][1]), d[6][4],1); EVAL Glue(Clock(d[0][2]), d[6][3],1); EVAL Glue(Clock(d[0][3]), d[6][2],1); EVAL Glue(Clock(d[0][4]), d[6][1],1); EVAL Glue(Clock(d[1][0]), d[9][0],1); EVAL Glue(Clock(d[1][1]), d[9][4],1); EVAL Glue(Clock(d[1][2]), d[9][3],1); EVAL Glue(Clock(d[1][3]), d[9][2],1); EVAL Glue(Clock(d[1][4]), d[9][1],1); EVAL Glue(Clock(d[2][0]), d[8][0],1); EVAL Glue(Clock(d[2][1]), d[8][4],1); EVAL Glue(Clock(d[2][2]), d[8][3],1); EVAL Glue(Clock(d[2][3]), d[8][2],1); EVAL Glue(Clock(d[2][4]), d[8][1],1); EVAL Glue(Clock(d[3][0]), d[7][0],1); EVAL Glue(Clock(d[3][1]), d[7][4],1); EVAL Glue(Clock(d[3][2]), d[7][3],1); EVAL Glue(Clock(d[3][3]), d[7][2],1); EVAL Glue(Clock(d[3][4]), d[7][1],1); EVAL Glue(Clock(d[4][0]), d[11][0],1); EVAL Glue(Clock(d[4][1]), d[11][4],1); EVAL Glue(Clock(d[4][2]), d[11][3],1); EVAL Glue(Clock(d[4][3]), d[11][2],1); EVAL Glue(Clock(d[4][4]), d[11][1],1); EVAL Glue(Clock(d[5][0]), d[10][0],1); EVAL Glue(Clock(d[5][1]), d[10][4],1); EVAL Glue(Clock(d[5][2]), d[10][3],1); EVAL Glue(Clock(d[5][3]), d[10][2],1); EVAL Glue(Clock(d[5][4]), d[10][1],1); fprintf(stderr, "Building the topology of the Poincare Dodecahedral Space:\n"); /* Return one @place not kill by the Glue Procedure */ return d[0][0]; } } /* END MakePoincare */ Place_t MakeSeifert() /* This procedure builds the 3-map so called as: "Seifert-Weber Space", generated by gluing @places of opposite wall of a triangulated dodecahedron, when one menber of each @place is matched to its conter- part after a rotation of three-tenth of a turn == 3/5 PI. Equal to the Lens4 procedure bellow. */ { ??? d = TriangulatedDodecahedron2(); { /* the opposite walls are: d[0] d[6] d[1] d[9] d[2] d[8] d[3] d[7] d[4] d[11] d[5] d[10] */ EVAL Glue(Clock(d[0][0]), d[6][3],1); EVAL Glue(Clock(d[0][1]), d[6][2],1); EVAL Glue(Clock(d[0][2]), d[6][1],1); EVAL Glue(Clock(d[0][3]), d[6][0],1); EVAL Glue(Clock(d[0][4]), d[6][4],1); EVAL Glue(Clock(d[1][0]), d[9][3],1); EVAL Glue(Clock(d[1][1]), d[9][2],1); EVAL Glue(Clock(d[1][2]), d[9][1],1); EVAL Glue(Clock(d[1][3]), d[9][0],1); EVAL Glue(Clock(d[1][4]), d[9][4],1); EVAL Glue(Clock(d[2][0]), d[8][3],1); EVAL Glue(Clock(d[2][1]), d[8][2],1); EVAL Glue(Clock(d[2][2]), d[8][1],1); EVAL Glue(Clock(d[2][3]), d[8][0],1); EVAL Glue(Clock(d[2][4]), d[8][4],1); EVAL Glue(Clock(d[3][0]), d[7][3],1); EVAL Glue(Clock(d[3][1]), d[7][2],1); EVAL Glue(Clock(d[3][2]), d[7][1],1); EVAL Glue(Clock(d[3][3]), d[7][0],1); EVAL Glue(Clock(d[3][4]), d[7][4],1); EVAL Glue(Clock(d[4][0]), d[11][3],1); EVAL Glue(Clock(d[4][1]), d[11][2],1); EVAL Glue(Clock(d[4][2]), d[11][1],1); EVAL Glue(Clock(d[4][3]), d[11][0],1); EVAL Glue(Clock(d[4][4]), d[11][4],1); EVAL Glue(Clock(d[5][0]), d[10][3],1); EVAL Glue(Clock(d[5][1]), d[10][2],1); EVAL Glue(Clock(d[5][2]), d[10][1],1); EVAL Glue(Clock(d[5][3]), d[10][0],1); EVAL Glue(Clock(d[5][4]), d[10][4],1); fprintf(stderr, "Building the topology of the Seifert-Weber Space:\n"); /* Return one @place not kill by the Glue Procedure */ return d[0][0]; } } /* END MakeSeifert */ Place_t MakeLens1() /* This procedure builds the 3-map generated by gluing @places of opposite wall of a triangulated dodecahedron, when one menber of each @place is matched to its conterpart after a rotation of 36 degrees of a turn. */ { ??? d = TriangulatedDodecahedron2(); { /* the opposite walls are: d[0] d[6] d[1] d[9] d[2] d[8] d[3] d[7] d[4] d[11] d[5] d[10] */ EVAL Glue(Clock(d[0][0]), d[6][0],1); EVAL Glue(Clock(d[0][1]), d[6][4],1); EVAL Glue(Clock(d[0][2]), d[6][3],1); EVAL Glue(Clock(d[0][3]), d[6][2],1); EVAL Glue(Clock(d[0][4]), d[6][1],1); EVAL Glue(Clock(d[1][0]), d[9][0],1); EVAL Glue(Clock(d[1][1]), d[9][4],1); EVAL Glue(Clock(d[1][2]), d[9][3],1); EVAL Glue(Clock(d[1][3]), d[9][2],1); EVAL Glue(Clock(d[1][4]), d[9][1],1); EVAL Glue(Clock(d[2][0]), d[8][0],1); EVAL Glue(Clock(d[2][1]), d[8][4],1); EVAL Glue(Clock(d[2][2]), d[8][3],1); EVAL Glue(Clock(d[2][3]), d[8][2],1); EVAL Glue(Clock(d[2][4]), d[8][1],1); EVAL Glue(Clock(d[3][0]), d[7][0],1); EVAL Glue(Clock(d[3][1]), d[7][4],1); EVAL Glue(Clock(d[3][2]), d[7][3],1); EVAL Glue(Clock(d[3][3]), d[7][2],1); EVAL Glue(Clock(d[3][4]), d[7][1],1); EVAL Glue(Clock(d[4][0]), d[11][0],1); EVAL Glue(Clock(d[4][1]), d[11][4],1); EVAL Glue(Clock(d[4][2]), d[11][3],1); EVAL Glue(Clock(d[4][3]), d[11][2],1); EVAL Glue(Clock(d[4][4]), d[11][1],1); EVAL Glue(Clock(d[5][0]), d[10][0],1); EVAL Glue(Clock(d[5][1]), d[10][4],1); EVAL Glue(Clock(d[5][2]), d[10][3],1); EVAL Glue(Clock(d[5][3]), d[10][2],1); EVAL Glue(Clock(d[5][4]), d[10][1],1); fprintf(stderr, "Building topology of Lens1 :\n"); /* Return one @place not kill by the Glue Procedure */ return d[0][0]; } } /* END MakeLens1 */ Place_t MakeLens2() /* This procedure builds the 3-map generated by gluing @places of opposite wall of a triangulated dodecahedron, when one menber of each @place is matched to its conterpart after a rotation of 108 degrees of a turn. */ { ??? d = TriangulatedDodecahedron2(); { /* the opposite walls are: d[0] d[6] d[1] d[9] d[2] d[8] d[3] d[7] d[4] d[11] d[5] d[10] */ EVAL Glue(Clock(d[0][0]), d[6][1],1); EVAL Glue(Clock(d[0][1]), d[6][0],1); EVAL Glue(Clock(d[0][2]), d[6][4],1); EVAL Glue(Clock(d[0][3]), d[6][3],1); EVAL Glue(Clock(d[0][4]), d[6][2],1); EVAL Glue(Clock(d[1][0]), d[9][1],1); EVAL Glue(Clock(d[1][1]), d[9][0],1); EVAL Glue(Clock(d[1][2]), d[9][4],1); EVAL Glue(Clock(d[1][3]), d[9][3],1); EVAL Glue(Clock(d[1][4]), d[9][2],1); EVAL Glue(Clock(d[2][0]), d[8][1],1); EVAL Glue(Clock(d[2][1]), d[8][0],1); EVAL Glue(Clock(d[2][2]), d[8][4],1); EVAL Glue(Clock(d[2][3]), d[8][3],1); EVAL Glue(Clock(d[2][4]), d[8][2],1); EVAL Glue(Clock(d[3][0]), d[7][1],1); EVAL Glue(Clock(d[3][1]), d[7][0],1); EVAL Glue(Clock(d[3][2]), d[7][4],1); EVAL Glue(Clock(d[3][3]), d[7][3],1); EVAL Glue(Clock(d[3][4]), d[7][2],1); EVAL Glue(Clock(d[4][0]), d[11][1],1); EVAL Glue(Clock(d[4][1]), d[11][0],1); EVAL Glue(Clock(d[4][2]), d[11][4],1); EVAL Glue(Clock(d[4][3]), d[11][3],1); EVAL Glue(Clock(d[4][4]), d[11][2],1); EVAL Glue(Clock(d[5][0]), d[10][1],1); EVAL Glue(Clock(d[5][1]), d[10][0],1); EVAL Glue(Clock(d[5][2]), d[10][4],1); EVAL Glue(Clock(d[5][3]), d[10][3],1); EVAL Glue(Clock(d[5][4]), d[10][2],1); fprintf(stderr, "Building topology of Lens2 :\n"); /* Return one @place not kill by the Glue Procedure */ return d[0][0]; } } /* END MakeLens2 */ Place_t MakeLens3() /* This procedure builds the 3-map generated by gluing @places of opposite wall of a triangulated dodecahedron, when one menber of each @place is matched to its conterpart after a rotation of 180 degree of a turn. */ { ??? d = TriangulatedDodecahedron2(); { /* the opposite walls are: d[0] d[6] d[1] d[9] d[2] d[8] d[3] d[7] d[4] d[11] d[5] d[10] */ EVAL Glue(Clock(d[0][0]), d[6][2],1); EVAL Glue(Clock(d[0][1]), d[6][1],1); EVAL Glue(Clock(d[0][2]), d[6][0],1); EVAL Glue(Clock(d[0][3]), d[6][4],1); EVAL Glue(Clock(d[0][4]), d[6][3],1); EVAL Glue(Clock(d[1][0]), d[9][2],1); EVAL Glue(Clock(d[1][1]), d[9][1],1); EVAL Glue(Clock(d[1][2]), d[9][0],1); EVAL Glue(Clock(d[1][3]), d[9][4],1); EVAL Glue(Clock(d[1][4]), d[9][3],1); EVAL Glue(Clock(d[2][0]), d[8][2],1); EVAL Glue(Clock(d[2][1]), d[8][1],1); EVAL Glue(Clock(d[2][2]), d[8][0],1); EVAL Glue(Clock(d[2][3]), d[8][4],1); EVAL Glue(Clock(d[2][4]), d[8][3],1); EVAL Glue(Clock(d[3][0]), d[7][2],1); EVAL Glue(Clock(d[3][1]), d[7][1],1); EVAL Glue(Clock(d[3][2]), d[7][0],1); EVAL Glue(Clock(d[3][3]), d[7][4],1); EVAL Glue(Clock(d[3][4]), d[7][3],1); EVAL Glue(Clock(d[4][0]), d[11][2],1); EVAL Glue(Clock(d[4][1]), d[11][1],1); EVAL Glue(Clock(d[4][2]), d[11][0],1); EVAL Glue(Clock(d[4][3]), d[11][4],1); EVAL Glue(Clock(d[4][4]), d[11][3],1); EVAL Glue(Clock(d[5][0]), d[10][2],1); EVAL Glue(Clock(d[5][1]), d[10][1],1); EVAL Glue(Clock(d[5][2]), d[10][0],1); EVAL Glue(Clock(d[5][3]), d[10][4],1); EVAL Glue(Clock(d[5][4]), d[10][3],1); fprintf(stderr, "Building topology of Lens3 :\n"); /* Return one @place not kill by the Glue Procedure */ return d[0][0]; } } /* END MakeLens3 */ Place_t MakeLens4() /* This procedure builds the 3-map generated by gluing @places of opposite wall of a triangulated dodecahedron, when one menber of each @place is matched to its conterpart after a rotation of 252 degree of a turn. (three-tenth of turn in the clockwise sense). */ { ??? d = TriangulatedDodecahedron2(); { /* the opposite walls are: d[0] d[6] d[1] d[9] d[2] d[8] d[3] d[7] d[4] d[11] d[5] d[10] */ EVAL Glue(Clock(d[0][0]), d[6][3],1); EVAL Glue(Clock(d[0][1]), d[6][2],1); EVAL Glue(Clock(d[0][2]), d[6][1],1); EVAL Glue(Clock(d[0][3]), d[6][0],1); EVAL Glue(Clock(d[0][4]), d[6][4],1); EVAL Glue(Clock(d[1][0]), d[9][3],1); EVAL Glue(Clock(d[1][1]), d[9][2],1); EVAL Glue(Clock(d[1][2]), d[9][1],1); EVAL Glue(Clock(d[1][3]), d[9][0],1); EVAL Glue(Clock(d[1][4]), d[9][4],1); EVAL Glue(Clock(d[2][0]), d[8][3],1); EVAL Glue(Clock(d[2][1]), d[8][2],1); EVAL Glue(Clock(d[2][2]), d[8][1],1); EVAL Glue(Clock(d[2][3]), d[8][0],1); EVAL Glue(Clock(d[2][4]), d[8][4],1); EVAL Glue(Clock(d[3][0]), d[7][3],1); EVAL Glue(Clock(d[3][1]), d[7][2],1); EVAL Glue(Clock(d[3][2]), d[7][1],1); EVAL Glue(Clock(d[3][3]), d[7][0],1); EVAL Glue(Clock(d[3][4]), d[7][4],1); EVAL Glue(Clock(d[4][0]), d[11][3],1); EVAL Glue(Clock(d[4][1]), d[11][2],1); EVAL Glue(Clock(d[4][2]), d[11][1],1); EVAL Glue(Clock(d[4][3]), d[11][0],1); EVAL Glue(Clock(d[4][4]), d[11][4],1); EVAL Glue(Clock(d[5][0]), d[10][3],1); EVAL Glue(Clock(d[5][1]), d[10][2],1); EVAL Glue(Clock(d[5][2]), d[10][1],1); EVAL Glue(Clock(d[5][3]), d[10][0],1); EVAL Glue(Clock(d[5][4]), d[10][4],1); fprintf(stderr, "Building topology of Lens4 :\n"); /* Return one @place not kill by the Glue Procedure */ return d[0][0]; } } /* END MakeLens4 */ Place_t MakeLens5() /* This procedure builds the 3-map generated by gluing @places of opposite wall of a triangulated dodecahedron, when one menber of each @place is matched to its conterpart after a rotation of 324 degree of a turn. */ { ??? d = TriangulatedDodecahedron2(); { /* the opposite walls are: d[0] d[6] d[1] d[9] d[2] d[8] d[3] d[7] d[4] d[11] d[5] d[10] */ EVAL Glue(Clock(d[0][0]), d[6][4],1); EVAL Glue(Clock(d[0][1]), d[6][3],1); EVAL Glue(Clock(d[0][2]), d[6][2],1); EVAL Glue(Clock(d[0][3]), d[6][1],1); EVAL Glue(Clock(d[0][4]), d[6][0],1); EVAL Glue(Clock(d[1][0]), d[9][4],1); EVAL Glue(Clock(d[1][1]), d[9][3],1); EVAL Glue(Clock(d[1][2]), d[9][2],1); EVAL Glue(Clock(d[1][3]), d[9][1],1); EVAL Glue(Clock(d[1][4]), d[9][0],1); EVAL Glue(Clock(d[2][0]), d[8][4],1); EVAL Glue(Clock(d[2][1]), d[8][3],1); EVAL Glue(Clock(d[2][2]), d[8][2],1); EVAL Glue(Clock(d[2][3]), d[8][1],1); EVAL Glue(Clock(d[2][4]), d[8][0],1); EVAL Glue(Clock(d[3][0]), d[7][4],1); EVAL Glue(Clock(d[3][1]), d[7][3],1); EVAL Glue(Clock(d[3][2]), d[7][2],1); EVAL Glue(Clock(d[3][3]), d[7][1],1); EVAL Glue(Clock(d[3][4]), d[7][0],1); EVAL Glue(Clock(d[4][0]), d[11][4],1); EVAL Glue(Clock(d[4][1]), d[11][3],1); EVAL Glue(Clock(d[4][2]), d[11][2],1); EVAL Glue(Clock(d[4][3]), d[11][1],1); EVAL Glue(Clock(d[4][4]), d[11][0],1); EVAL Glue(Clock(d[5][0]), d[10][4],1); EVAL Glue(Clock(d[5][1]), d[10][3],1); EVAL Glue(Clock(d[5][2]), d[10][2],1); EVAL Glue(Clock(d[5][3]), d[10][1],1); EVAL Glue(Clock(d[5][4]), d[10][0],1); fprintf(stderr, "Building topology of Lens5 :\n"); /* Return one @place not kill by the Glue Procedure */ return d[0][0]; } } /* END MakeLens5 */ Place_t MakePseudo() /* Build the tridimensional cellular map so called "PseudoManifold". This map under this gluing will produce degenerate configuration. */ { ??? ca = MakeFunnyBall(); { GlueBall(ca.p[0], PrevF(ca.p[1])); GlueBall(ca.p[1], PrevF(ca.p[2])); fprintf(stderr, "Building Topology of PseudoManifold: \n"); /* Return one @place not kill by the GlueBall Procedure */ return ca.p[2]; } } /* END MakePseudo */ /* UNUSED */ Place_t MakeCm2t_H1() /* This complex is homeomorphic to cm2t manifold */ { ??? a = MakeTetraTopo(Order; with (Order), double b = MakeTetraTopo(Order,Order) ){ Glue(Spin(b[3]),a[2],Order); Glue(Spin(a[3]),b[2],Order); Glue(Spin(b[1]),b[0],Order); Glue(Spin(a[1]),a[0],Order); fprintf(stderr, "Building topology of cm2t-h1: \n"); /* Return one @place not kill by the Glue Procedure */ return Spin(b[1]); } } /* END MakeCm2t_H1 */ /* UNUSED */ Place_t MakeCm2t_H2() /* This complex is homeomorphic to cm2t manifold */ { ??? a = MakeTetraTopo(Order; with (Order), double b = MakeTetraTopo(Order,Order) ){ Glue(Spin(a[6]),b[3],Order); Glue(Spin(a[7]),b[2],Order); Glue(Spin(b[1]),b[0],Order); Glue(Spin(a[1]),a[0],Order); fprintf(stderr, "Building topology of cm2t-h2: \n"); /* Return one @place not kill by the Glue Procedure */ return Spin(a[6]); } } /* END MakeCm2t_H2 */ /* UNUSED */ Place_t MakeCm2t_H3() /* This complex is homeomorphic to cm2t manifold */ { ??? a = MakeTetraTopo(Order; with (Order), double b = MakeTetraTopo(Order,Order) ){ Glue(Spin(a[7]),b[3],Order); Glue(Spin(a[6]),b[2],Order); Glue(Spin(b[1]),b[0],Order); Glue(Spin(a[1]),a[0],Order); fprintf(stderr, "Building topology of cm2t-h3:\n"); /* Return one @place not kill by the Glue Procedure */ return Spin(a[7]); } } /* END MakeCm2t_H3 */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "sphere") )) { o->shape = Shape_Sphere } else if (0 == strcmp(o->shapeName,"cm2t") )){ o->shape = Shape_Cm2t } else if (0 == strcmp(o->shapeName,"torus") )){ o->shape = Shape_Torus } else if (0 == strcmp(o->shapeName,"pseudo") )){ o->shape = Shape_Pseudo } else if (0 == strcmp(o->shapeName,"seifert"))){ o->shape = Shape_Seifert } else if (0 == strcmp(o->shapeName,"poincare"))){ o->shape = Shape_Poincare } else if (0 == strcmp(o->shapeName,"lens1"))){ o->shape = Shape_Lens1 } else if (0 == strcmp(o->shapeName,"lens2"))){ o->shape = Shape_Lens2 } else if (0 == strcmp(o->shapeName,"lens3"))){ o->shape = Shape_Lens3 } else if (0 == strcmp(o->shapeName,"lens4"))){ o->shape = Shape_Lens4 } else if (0 == strcmp(o->shapeName,"lens5"))){ o->shape = Shape_Lens5 } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeComplex \\\n" \ " -shape { Seifert | Poincare | ..}\n"); END¦ } } return o; } /* END GetOptions */ /* end MakeComplex */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeComplexWf.c #define PROG_NAME "MakeComplexWf" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeComplexWf_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Generates ".tp",".tb",".st" and ".ma" files for some simples tridimensional maps with boundary. The node coordinates are random numbers in [-1..+1]. */ #define MakeComplexWf_C_author \ "Created by L. A. P. Lozada, 1999-2000.\n" \ "Revisions:\n" \ " 30-08-2000 : nice version of the {MakeOctahedron} procedure." // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE #include // #INCLUDE TYPE double Shape_t = { Triang, Tetra1, Tetra2, Tetra3, TetraRe, CubeTriang, BigCube, Octa1, Octa2, Octa3, Pyramid }; typedef struct Options_t { uint order; Shape_t shape; char *shapeName; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { ElemTableRec_t top; Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakeMap(o->shape; with ( o->order) ){ top = MakeElemTable(m); Coords_t c = GenCoords(&top);; { /* set the edge and wall roots */ for (i = 0; i < top.wall.ne; i++) { ??? f = top.wall[i]; { f->root = f->num; } }; for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i]; { e->root = e->num; } }; /* Now writes */ WriteTopology(o->shapeName & "-" & Fmt.Int(o->order), top, "Created by MakeComplexWf: " & o->shapeName & "-" & Fmt.Int(o->order) \ ".tp on " & Today()); WriteState(o->shapeName & "-" & Fmt.Int(o->order), top, c, "Created by MakeComplexWf: " & o->shapeName & "-" & Fmt.Int(o->order) \ ".st on " & Today() &"\nRandom Geometry"); WriteMaterials(o->shapeName & "-" & Fmt.Int(o->order), top, "Created by MakeComplexWf: " & o->shapeName & "-" & Fmt.Int(o->order) \ ".ma on " & Today()); } return 0; } Place_t MakeMap(shape: Shape_t; order: uint) { CASE shape OF break; case Shape_Triang: return Squared.MakeTriangle(); break; case Shape_Tetra1: return MakeTetra(order); break; case Shape_Tetra2: return MakeTetra2(order); break; case Shape_Tetra3: return MakeTetra3(order); break; case Shape_TetraRe: return Make12Fold(order); break; case Shape_CubeTriang: return MakeCubeTriang(order); break; case Shape_BigCube: return MakeBigcube(order); break; case Shape_Octa1: return MakeOctahedron(order); break; case Shape_Octa2: return MakeTwoOctaGlue(order); break; case Shape_Octa3: return MakeThreeOctaGlue(order); break; case Shape_Pyramid: return MakePyramid(order); } } /* END MakeMap */ /* Shape_t builders: */ PROCEDURE MakeTetra(/* UNUSED */ or: uint): Place_t == /* unglued topological tetrahedron */ { ??? a = Squared.MakeTetrahedron(); { fprintf(stderr,"Building topology of one topological tetrahedron\n"); return a[0]; } } /* END MakeTetra */ PROCEDURE MakeOctahedron(/* UNUSED */ or: uint): Place_t == { ??? o = Squared.MakeOctahedron(); { fprintf(stderr, "Building the topology of one octahedral cell\n"); return o[0]; } } /* END MakeOctahedron */ PROCEDURE MakeTwoOctaGlue(/* UNUSED */ or: uint): Place_t == /* Builds the topology of the map with two octahedral cell gluing them along of a common wall. */ { ??? o1 = Squared.MakeOctahedron(); ??? o2 = Squared.MakeOctahedron(); { Glue(Spin(o1[1]), o2[6],1); fprintf(stderr,"Building the topology of two octahedral cells\n"); return o1[0]; } } /* END MakeTwoOctaGlue */ PROCEDURE MakeThreeOctaGlue(/* UNUSED */ or: uint): Place_t == /* Build the topology of the map with three octahedral cell gluing them along of common @{edge->?}. */ { ??? o1 = Squared.MakeOctahedron(); ??? o2 = Squared.MakeOctahedron(); ??? o3 = Squared.MakeOctahedron(); { Glue(Spin(o1[1]), o2[6],1); Glue(Spin(o1[5]), Spin(PrevE(o3[2])), 1, TRUE); Glue(Clock(NextE(o3[1])), o2[2],1); fprintf(stderr,"Building the topology of three octahedral cells\n"); return o1[0]; } } /* END MakeThreeOctaGlue */ PROCEDURE Make12Fold(/* UNUSED */ or: uint): Place_t == /* This procedure builds a refined tetrahedron as the subdivision scheme know as "12fold", but with one octahedral cell more eigth tetrahedral cells. */ { ??? o = Squared.MakeOctahedron(); ??? t0 = Squared.MakeTetrahedron(); ??? t1 = Squared.MakeTetrahedron(); ??? t2 = Squared.MakeTetrahedron(); ??? t3 = Squared.MakeTetrahedron(); ??? t4 = Squared.MakeTetrahedron(); ??? t5 = Squared.MakeTetrahedron(); ??? t6 = Squared.MakeTetrahedron(); ??? t7 = Squared.MakeTetrahedron(); { /* first glue the 8 tetrahedra to the central octahedron */ Glue(t0[0],o[0],1); /* 5 */ Glue(t1[0],o[1],1); /* 6 */ Glue(t2[0],o[2],1); /* 7 */ Glue(t3[0],o[3],1); /* 8 */ Glue(t4[0],NextF(t0[0]),1); /* 5 */ Glue(t5[0],NextF(t1[0]),1); /* 6 */ Glue(t6[0],NextF(t2[0]),1); /* 7 */ Glue(t7[0],NextF(t3[0]),1); /* 8 */ Glue(o[4],NextF(t4[0]),1); /* 5 */ Glue(o[5],NextF(t5[0]),1); /* 6 */ Glue(o[6],NextF(t6[0]),1); /* 7 */ Glue(o[7],NextF(t7[0]),1); /* 8 */ Glue(Clock(NextF(PrevE(t1[0]))),NextF(NextE(t0[0])),1); /* 9 */ Glue(Clock(NextF(PrevE(t2[0]))),NextF(NextE(t1[0])),1); /* 10 */ Glue(Clock(NextF(PrevE(t3[0]))),NextF(NextE(t2[0])),1); /* 11 */ Glue(Clock(NextF(PrevE(t0[0]))),NextF(NextE(t3[0])),1); /* 12 */ Glue(PrevF(NextE(o[4])),Clock(PrevF(PrevE(o[5]))), 1, TRUE); Glue(PrevF(NextE(o[5])),Clock(PrevF(PrevE(o[6]))), 1, TRUE); Glue(PrevF(NextE(o[6])),Clock(PrevF(PrevE(o[7]))), 1, TRUE); Glue(PrevF(NextE(o[7])),Clock(PrevF(PrevE(o[4]))), 1, TRUE); fprintf(stderr, "Building a refined tetrahedron with an octahedral cell in the center\n"); return t0[0]; } } /* END Make12Fold */ Place_t MakeTetra2(or: uint) /* Glues two topological tetrahedron along a one triangulated wall. */ { ??? a = MakeTetraTopo(or; with (or), double b = MakeTetraTopo(or,or) ){ Glue(Spin(b[3]),a[2],or); fprintf(stderr, "Building the topology of 2 tetrahedra glued along one triang. wall\n"); return b[3]; } } /* END MakeTetra2 */ Place_t MakeTetra3(or: uint) /* Glues three topological tetrahedron two by two along a common @{edge->?}, i.e. builds a map "@{edge->?}star" of degree three. */ { ??? a = MakeTetraTopo(or; with (or), double b = MakeTetraTopo(or,or); double c = MakeTetraTopo(or,or) ){ Glue(Spin(a[1]),b[0],or); Glue(Spin(b[1]),c[0],or); Glue(Spin(c[1]),a[0],or); fprintf(stderr, "Building the topology of 3 tetrahedra glued along a common @{edge->?}\n"); return a[1]; } } /* END MakeTetra3 */ Place_t MakeCubeTriang(or: uint) /* A simple triangulated cube, building by the glue of six simples tetrahedron. */ { ??? a = MakeTetraTopo(or; with (or), double b = MakeTetraTopo(or,or); double c = MakeTetraTopo(or,or); double d = MakeTetraTopo(or,or); double e = MakeTetraTopo(or,or); double f = MakeTetraTopo(or,or) ){ Glue(Spin(b[1]),a[0],or); Glue(Spin(c[1]),b[0],or); Glue(Spin(d[1]),c[0],or); Glue(Spin(e[1]),d[0],or); Glue(Spin(f[1]),e[0],or); Glue(Spin(a[1]),f[0],or); fprintf(stderr,"Building the topology of one triangulated cube\n"); return a[1]; } } /* END MakeCubeTriang */ Place_t MakeBigcube(or: uint) { ??? a = Squared.MakeBigCube(or); { fprintf(stderr, "Building the topology of an array of cubes\n"); return a[0,0,0]; } } /* END MakeBigcube */ Place_t MakePyramid(or: uint) { ??? a = Squared.MakePyramid(or); { fprintf(stderr, "Building the topology of a pyramid with base as a " \ Fmt.Int(or) & "-gon\n"); return a[0]; } } /* END MakePyramid */ /* UNUSED */ PROCEDURE Prt (Place_t @p) { fprintf(stderr, "wedge: "); PrintPlace(stderr, a, 1); fprintf(stderr, " fnext: "); PrintPlace(stderr, NextF(a)); fprintf(stderr, "\n"); } /* END Prt */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 1, 9); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName , "tetra1"))) { o->shape = Shape_Tetra1 } else if (0 == strcmp(o->shapeName, "tetra2"))){ o->shape = Shape_Tetra2 } else if (0 == strcmp(o->shapeName, "tetra3"))){ o->shape = Shape_Tetra3 } else if (0 == strcmp(o->shapeName, "tetrare"))){ o->shape = Shape_TetraRe } else if (0 == strcmp(o->shapeName, "cubetriang"))){ o->shape = Shape_CubeTriang } else if (0 == strcmp(o->shapeName, "bigcube"))){ o->shape = Shape_BigCube } else if (0 == strcmp(o->shapeName, "octa1"))){ o->shape = Shape_Octa1 } else if (0 == strcmp(o->shapeName, "octa2"))){ o->shape = Shape_Octa2 } else if (0 == strcmp(o->shapeName, "octa3"))){ o->shape = Shape_Octa3 } else if (0 == strcmp(o->shapeName, "pyramid"))){ o->shape = Shape_Pyramid } else if (0 == strcmp(o->shapeName, "triangle"))){ o->shape = Shape_Triang } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeComplexWf -order \\\n" \ " -shape { tetra1 | ... | cubetriang | ...}\n"); END¦ } } return o; } /* END GetOptions */ /* end MakeComplexWf */ /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeGem.c #define PROG_NAME "MakeGem" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeGem_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program builds the topology of some Sosten'es 3-Gems */ #include // #INCLUDE // #INCLUDE // #INCLUDE #include #include TYPE Handle == ARRAY[0..3] OF Place_t; double Shape_t = { projective, r24_20}; typedef struct Options_t { Shape_t shape; char *shapeName; } REF ARRAY OF Handle handles ; Handle MakeGemCell() Handle *ha; { ??? te = MakeTetraTopo(1,1); with (, double h0 = Spin(Clock(PrevE(te[0]))); double h1 = Spin(Clock(PrevE(te[6]))); double h2 = NextE(te[1]); double h3 = Spin(Clock(PrevE(te[2]))) ){ ha[0] = h0; ha[1] = h1; ha[2] = h2; ha[3] = h3; } return ha; } /* END MakeGemCell */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ { if (0 == strcmp(o->shapeName,"projective"))) { handles = NEW(REF ARRAY OF Handle, 8); for (i = 0; i < 8; i++) { handles[i] = MakeGemCell(); }; /* Projective Space */ GlueGem(0, 1, 3); GlueGem(0, 6, 0); GlueGem(0, 4, 1); GlueGem(0, 3, 2); GlueGem(1, 2, 2); GlueGem(1, 5, 1); GlueGem(1, 7, 0); GlueGem(2, 6, 1); GlueGem(2, 4, 0); GlueGem(2, 3, 3); GlueGem(3, 7, 1); GlueGem(3, 5, 0); GlueGem(4, 7, 2); GlueGem(4, 5, 3); GlueGem(5, 6, 2); GlueGem(6, 7, 3); } else if (0 == strcmp(o->shapeName,"r24-20"))){ handles = NEW(REF ARRAY OF Handle, 24); for (i = 0; i <= (23); i++) { handles[i] = MakeGemCell(); }; /* Cor 0: */ GlueGem( 1-1, 2-1, 0); GlueGem( 3-1, 4-1, 0); GlueGem( 5-1, 6-1, 0); GlueGem( 7-1, 8-1, 0); GlueGem( 9-1, 10-1, 0); GlueGem(11-1, 12-1, 0); GlueGem(13-1, 14-1, 0); GlueGem(15-1, 16-1, 0); GlueGem(17-1, 18-1, 0); GlueGem(19-1, 20-1, 0); GlueGem(21-1, 22-1, 0); GlueGem(23-1, 24-1, 0); /* Cor 1: */ GlueGem( 1-1, 8-1, 1); GlueGem( 2-1, 3-1, 1); GlueGem( 4-1, 5-1, 1); GlueGem( 6-1, 7-1, 1); GlueGem( 9-1, 14-1, 1); GlueGem(10-1, 11-1, 1); GlueGem(12-1, 13-1, 1); GlueGem(15-1, 20-1, 1); GlueGem(16-1, 17-1, 1); GlueGem(18-1, 19-1, 1); GlueGem(21-1, 24-1, 1); GlueGem(22-1, 23-1, 1); /* Cor 2: */ GlueGem( 1-1, 20-1, 2); GlueGem( 2-1, 19-1, 2); GlueGem( 3-1, 18-1, 2); GlueGem( 4-1, 17-1, 2); GlueGem( 5-1, 16-1, 2); GlueGem( 6-1, 13-1, 2); GlueGem( 7-1, 24-1, 2); GlueGem( 8-1, 9-1, 2); GlueGem(10-1, 23-1, 2); GlueGem(11-1, 22-1, 2); GlueGem(12-1, 21-1, 2); GlueGem(14-1, 15-1, 2); /* Cor 3: */ GlueGem( 1-1, 18-1, 3); GlueGem( 2-1, 17-1, 3); GlueGem( 3-1, 16-1, 3); GlueGem( 4-1, 9-1, 3); GlueGem( 5-1, 24-1, 3); GlueGem( 6-1, 11-1, 3); GlueGem( 7-1, 20-1, 3); GlueGem( 8-1, 19-1, 3); GlueGem(10-1, 15-1, 3); GlueGem(12-1, 23-1, 3); GlueGem(13-1, 22-1, 3); GlueGem(14-1, 21-1, 3); } ??? top = MakeElemTable(handles[0][0]); Coords_t c = GenCoords(&top);; ??? name = o->shapeName; { WriteTopology(name, top, "Created by MakeGem: " & name & ".tp on " \ Today()); WriteMaterials(name, top, "Created by MakeGem: " & name& ".ma on " \ Today()); WriteState(name, top, c, "Created by MakeGem: " & name & ".st on " \ Today() &"\nRandom Geometry"); } return 0; } PROCEDURE GlueGem(i, j, cor : uint) { EVAL Triangulation.Glue(Spin(handles[i,cor]), handles[j,cor],1); } /* END GlueGem */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "projective") )) { o->shape = Shape_projective } else if (0 == strcmp(o->shapeName, "r24-20"))){ o->shape = Shape_r24_20 } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeGem -shape { projective | r24-20 }\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } MakeGem. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeGemR2420.c /* Cor 0: */ GlueGem( 1-1, 2-1, 0); GlueGem( 3-1, 4-1, 0); GlueGem( 5-1, 6-1, 0); GlueGem( 7-1, 8-1, 0); GlueGem( 9-1, 10-1, 0); GlueGem(11-1, 12-1, 0); GlueGem(13-1, 14-1, 0); GlueGem(15-1, 16-1, 0); GlueGem(17-1, 18-1, 0); GlueGem(19-1, 20-1, 0); GlueGem(21-1, 22-1, 0); GlueGem(23-1, 24-1, 0); /* Cor 1: */ GlueGem( 1-1, 8-1, 1); GlueGem( 2-1, 3-1, 1); GlueGem( 4-1, 5-1, 1); GlueGem( 6-1, 7-1, 1); GlueGem( 9-1, 14-1, 1); GlueGem(10-1, 11-1, 1); GlueGem(12-1, 13-1, 1); GlueGem(15-1, 20-1, 1); GlueGem(16-1, 17-1, 1); GlueGem(18-1, 19-1, 1); GlueGem(21-1, 24-1, 1); GlueGem(22-1, 23-1, 1); /* Cor 2: */ GlueGem( 1-1, 20-1, 2); GlueGem( 2-1, 19-1, 2); GlueGem( 3-1, 18-1, 2); GlueGem( 4-1, 17-1, 2); GlueGem( 5-1, 16-1, 2); GlueGem( 6-1, 13-1, 2); GlueGem( 7-1, 24-1, 2); GlueGem( 8-1, 9-1, 2); GlueGem(10-1, 23-1, 2); GlueGem(11-1, 22-1, 2); GlueGem(12-1, 21-1, 2); GlueGem(14-1, 15-1, 2); /* Cor 3: */ GlueGem( 1-1, 18-1, 3); GlueGem( 2-1, 17-1, 3); GlueGem( 3-1, 16-1, 3); GlueGem( 4-1, 9-1, 3); GlueGem( 5-1, 24-1, 3); GlueGem( 6-1, 11-1, 3); GlueGem( 7-1, 20-1, 3); GlueGem( 8-1, 19-1, 3); GlueGem(10-1, 15-1, 3); GlueGem(12-1, 23-1, 3); GlueGem(13-1, 22-1, 3); GlueGem(14-1, 21-1, 3); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakePolygon.c #define PROG_NAME "MakePolygon" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakePolygon_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Generates ".tp",".tb",".ma" and ".st" files for n-gons, for 2 <= n <= 20. */ #define MakePolygon_C_author \ "Implemented by L. A. P. Lozada, 1999.\n" \ "Modified by L. A. P. Lozada on 99-11-11." // #INCLUDE #include #include // #INCLUDE // #INCLUDE #include // #INCLUDE #include typedef struct Options_t { uint order; bool_t fixed; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Coords_t c; char *tag; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakePolygon(o->order); ??? top = MakeElemTable(m); ??? name = "gon-" & Fmt.Int(o->order); { c = r4_vec_new(top.node.ne); if (! o->fixed) { c = GenCoords(top); tag = "-ran"; WriteTopology(name & tag,top,"Created by MakePolygon: gon-" \ Fmt.Int(o->order) & "-ran.tp on " & Today()); WriteState(name&tag,top,c^, "Created by MakePolygon: gon-" & Fmt.Int(o->order) & "-ran.st on " \ Today() & "\nRandom Geometry"); WriteMaterials(name & tag,top,"Created by MakePolygon: gon-" \ Fmt.Int(o->order) & "-ran.ma on " & Today()); } else { c = FixCoordsGon(o->order,m,top); tag = "-fix"; WriteTopology(name & tag,top,"Created by MakePolygon: gon-" \ Fmt.Int(o->order) & "-fix.tp on " & Today()); WriteState(name & tag, top,c^, "Created by MakePolygon: gon-" & Fmt.Int(o->order) & "-fix.st on " \ Today()); WriteMaterials(name & tag,top,"Created by MakePolygon: gon-" \ Fmt.Int(o->order) & "-fix.ma on " & Today()); } return 0; } Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 2,40); o->fixed = argparser_keyword_present(pp, "-fixed"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakePolygon -order <2-40> \\\n" \ " [ -fixed ]\n"); END¦ } } return o; } /* END GetOptions */ /* end MakePolygon */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeManifold.c #define PROG_NAME "MakeManifold" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeManifold_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program generates ".tp",".tb",".st" and ".ma" files for some sim- ples tridimensional maps with topologies of three-manifolds, such as, the Hypersphere S^{3} and the Hypertorus T^{3}. The node coordinates are random numbers in [-1..+1]. The difference with the "MakeComplex" program (that also builds 3D maps homeomorphic to 3D manifolds) is that, "MakeComplex" program uses polyhe- dra gluing scheme as a single cell, conversely, "MakeManifold" uses a subdivision or refinement of the cells gluing scheme. The maps builds through the "MakeComplex" program results in degeneracies conversely, "MakeManifold" produces maps that can be not result in degene- racies, depending on the "order" option. */ // #INCLUDE // #INCLUDE // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE #include TYPE double Shape_t = { /* subdivided cells, such as builds by the: */ Sphere1, /* "libm3triang.Triangualtion.MakeTetraTopo" procedure */ Sphere2, /* "libm3subdi.Refine.MakeTetra" procedure */ Torus, /* "libm3squared.Squared.MakeBigCube" procedure */ TorusNet }; typedef struct Options_t { shape: Shape_t; shapeName: char *; order: uint; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakeMap(o->shape; with (o->order), double top = MakeElemTable(m); double c = GenCoords(top)^ ){ /* Set the root elements for edges and walls */ for (i = 0; i < top.wall.ne; i++) { Wall_t f = top.wall.e[i]; f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = top.edge.e[i]; e->root = e->num; } WriteTopology( o->shapeName & "-" & Fmt.Int(o->order), top, "Created by MakeManifold: " & o->shapeName & "-" & Fmt.Int(o->order) & ".tp on " & Today()); WriteState( o->shapeName & "-" & Fmt.Int(o->order),top,c,"Created by MakeManifold: " \ o->shapeName & "-" & Fmt.Int(o->order) & ".st on " & Today() \ "\nRandom Geometry"); WriteMaterials( o->shapeName & "-" & Fmt.Int(o->order), top, "Created by MakeManifold: " \ o->shapeName & "-" & Fmt.Int(o->order) & ".ma on " & Today()); return 0; } Place_t MakeMap(shape: Shape_t; order: uint) { CASE shape OF break; case Shape_Sphere1: return MakeSphere1(order); break; case Shape_Sphere2: return MakeSphere2(order); break; case Shape_Torus: return MakeTorus(order); break; case Shape_TorusNet: return MakeTorusNet(order); } } /* END MakeMap */ Place_t MakeTorus(uint order) /* A cube (the gluing scheme for the Hypertorus map) is modeled as a tridimensional array of smaller cubes, as returned by the "libm3squared.Squared.MakeBigCube" procedure. */ { fprintf(stderr, "First, we build the 3D array of cubes\n"); ??? a = MakeBigCube(order); ??? p = a[order-1; with (0,0], double top = MakeElemTable(p) ){ /* Set all elements (nodes, @{edge->?}s, walls), as non-existing */ for (i = 0; i < top.wall.ne; i++) { with ( Wall_t f = top.wall.e[i] DO f->exists = FALSE; } } for (i = 0; i < top.edge.ne; i++) { with ( Edge_t e = top.edge.e[i] DO e->exists = FALSE; } } for (i = 0; i < top.node.ne; i++) { with ( double v = top.node[i] DO v->exists = FALSE; } } /* Now emphasize the original elements (nodes,@{edge->?}s,walls) */ SetCubeProperties(a, order, top); GlueBigCube(Clock(Spin(PrevF(a[order-1,0,0]))), Spin(PrevF(PrevE(PrevE(a[0,0,0])))), order); GlueBigCube(Spin(a[order-1,0,1]), Clock(Spin(a[order-1,0,0])),order); GlueBigCube(Spin(NextF(PrevE(a[0,0,1]))), Clock(Spin(NextF(NextE(a[0,order-1,1])))), order); fprintf(stderr, "Building topology of Torus: \n"); /* Return one @place not kill by the GlueBigCube procedure */ return a[0,0,1]; } } /* END MakeTorus */ Place_t MakeTorusNet(uint order) /* A cube (the gluing scheme for the Hypertorus map) is modeled as a tridimensional array of smaller cubes, as returned by the "libm3squared.Squared.MakeBigCube" procedure. */ { fprintf(stderr, "First, we build the 3D array of cubes\n"); ??? a = MakeBigCube(order); { /* Set all elements (nodes, @{edge->?}s, walls), as non-existing */ GlueBigCube(Clock(Spin(PrevF(a[order-1,0,0]))), Spin(PrevF(PrevE(PrevE(a[0,0,0])))), order); GlueBigCube(Spin(a[order-1,0,1]), Clock(Spin(a[order-1,0,0])),order); GlueBigCube(Spin(NextF(PrevE(a[0,0,1]))), Clock(Spin(NextF(NextE(a[0,order-1,1])))), order); fprintf(stderr, "Building topology of Torus: \n"); /* Return one @place not kill by the GlueBigCube procedure */ return a[0,0,1]; } } /* END MakeTorusNet */ Place_t MakeSphere1(uint order) /* A tetrahedron (the gluing scheme for the Hypersphere map) is a bidimensional array of smaller tetrahedra, as returned by the "libm3triang.Triangulation. MakeTetraTopo" procedure. */ { ??? a = MakeTetraTopo(order; with (order) ){ EmphasizeTetrahedron(a[0], a[3], order); Glue(Spin(a[1]),a[0],order); Glue(Spin(a[3]),a[2],order); fprintf(stderr, "Building topology of Sphere1: \n"); /* Return one @place not kill by the Glue Procedure */ return a[1]; } } /* END MakeSphere1 */ Place_t MakeSphere2(uint order) /* A tetrahedron (the gluing scheme for the Hypersphere map) is regular refinement of a single tetrahedron, as returned by the "libm3subdi.Refine.MakeTetra" procedure. The number of smaller tetrahedra is computed by the recursion: "5/3 order^{3} - 2/3 order". */ { ??? a = MakeMaximalGlue(order); { fprintf(stderr, "Building topology of Sphere2:\n"); /* Return one @place not kill by the Glue Procedure */ return a; } } /* END MakeSphere2 */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "sphere1") )) { o->shape = Shape_Sphere1 } else if (0 == strcmp(o->shapeName,"sphere2") )){ o->shape = Shape_Sphere2 } else if (0 == strcmp(o->shapeName,"torus") )){ o->shape = Shape_Torus } else if (0 == strcmp(o->shapeName,"torusnet") )){ o->shape = Shape_TorusNet } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 1, 9); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr,"Usage: MakeManifold \\\n" \ " -shape { sphere1 | sphere2 | torus }\\\n" \ " -order \n"); END¦ } } return o; } /* END GetOptions */ /* end MakeManifold */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeNOComplex.c #define PROG_NAME "MakeNOComplex" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeNOComplex_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program generates ".tp",".tb",".st" and ".ma" files for another tridimensional complexes with topologies of pseudo three-manifolds. The node coordinates are random numbers in [-1..+1]. Notice: we need to modify the facet-edge data structure for modeling ------ those non orientable 3D complex, or use another data structure */ #define MakeNOComplex_C_author \ "Implemented by L. Lozada, 1999-2000." // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE #include // #INCLUDE TYPE double Shape_t = {Projective}; typedef struct Options_t { Shape_t shape; char *shapeName; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakeMap(o->shape); ??? top = MakeElemTable(m); Coords_t c = GenCoords(&top);; { WriteTopology(o->output, tag, &top, topo_cmt); // shapeName MakeNOComplex shapeName WriteState( o->shapeName, top, c,"Created by MakeNOComplex: " & o->shapeName \ ".st on " & Today() & "\nRandom Geometry" ); WriteMaterials(o->output, tag, &top, topo_cmt); // shapeName MakeNOComplex shapeName return 0; } Place_t MakeMap(Shape_t shape) { CASE shape OF break; case Shape_Projective: return MakeProjective(); } } /* END MakeMap */ Place_t MakeProjective() /* Notice: we need to modify the facet-edge data structure for modeling this non orientable 3D complex. */ { ??? co = MakeCube(); { GlueCube(co.e[1], Clock(PrevF(co.e[2]))); GlueCube(co.e[5], co.e[0]); GlueCube(co.e[4], NextE(NextE(co.e[2]))); fprintf(stderr, "Building Topology of ProjectiveSpace: \n"); /* Return one @place not kill by the GlueBall Procedure */ return co.e[0]; } } /* END MakeProjective */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "projective"))) { o->shape = Shape_Projective } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr,"Usage: OtherComplex -shape { projective }\n"); END¦ } } return o; } /* END GetOptions */ /* end MakeNOComplex */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeObjectTriang.c #define PROG_NAME "MakeObjectTriang" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeObjectTriang_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Generates ".tp",".tb",".ma" and ".st" files for some simples triangulated and convex objects such as "sausage", bidimensional "torus" with and with out one twist in R^{4}. The node coordinates are random numbers in [-1..+1]. #define MakeObjectTriang_C_author \ "Modified by L.A.P.Lozada on 2000-03-19." // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include #include CONST double order = 1; TYPE double @PLACES = ARRAY[0..3] OF Place_t; double Shape_t = {Torus2D, Torus2H, Sausage}; typedef struct Options_t { Shape_t shape; char *shapeName; uint gridOrder; } PROCEDURE Main() VAR { ElemTableRec_t top; Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakeObject(o->shape; with ( o->gridOrder), double name = o->shapeName & "-" & Fmt.Int(o->gridOrder) ){ Octf.EnumWedges(m,SetOrgAll,FALSE); top = MakeElemTable(m,1); if (0 == strcmp(o->shapeName, "torus2d"))) { assert(top->node.ne == 8 + (o->gridOrder-1) * 4 - 4); assert(top->NE == 19 + (o->gridOrder-1) * 14 - 5); assert(top->wall.ne == 18 + (o->gridOrder-1) * 16 - 2); assert(top->wall.nelE== 54 + (o->gridOrder-1) * 48 - 6); assert(top->cell.ne == 6 * o->gridOrder); } else if (0 == strcmp(o->shapeName, "sausage"))){ assert(top->node.ne == 8 + (o->gridOrder-1) * 4); assert(top->NE == 19 + (o->gridOrder-1) * 14); assert(top->wall.ne == 18 + (o->gridOrder-1) * 16); assert(top->wall.nelE== 54 + (o->gridOrder-1) * 48); assert(top->cell.ne == 6 * o->gridOrder); } ??? c = GenCoords(top)^; { WriteTopology( name, top, "Created by MakeObjectTriang: " & o->shapeName \ ".tp on " & Today()); WriteTable( name, top, "Created by MakeObjectTriang: " & o->shapeName \ ".tb on " & Today()); WriteState( name, top, c,"Created by MakeObjectTriang: " & o->shapeName \ ".st on " & Today() & "\nRandom Geometry"); WriteMaterials( name, top,"Created by MakeObject: " & o->shapeName \ ".ma on " & Today()); } } } /* END Main */ Place_t MakeObject(shape: Shape_t; order: uint) { CASE shape OF break; case Shape_Torus2D: return MakeTorus2D(order); break; case Shape_Torus2H: return MakeTorus2H(order); break; case Shape_Sausage: return MakeSausage(order); } } /* END MakeObject */ /* Shape_t builders: */ PROCEDURE MakeCubeT() : SixPlaces_t == Place_t co.e[5+1]; { ??? n = order; ??? ca = MakeTetraTopo(n; with (n), double cb = MakeTetraTopo(n,n); double cc = MakeTetraTopo(n,n); double cd = MakeTetraTopo(n,n); double ce = MakeTetraTopo(n,n); double cf = MakeTetraTopo(n,n) ){ Glue(Spin(cb.e[1]),ca.p[0],n); Glue(Spin(cc.e[1]),cb.e[0],n); Glue(Spin(cd[1]),cc.e[0],n); Glue(Spin(ce[1]),cd[0],n); Glue(Spin(cf[1]),ce[0],n); Glue(Spin(ca.p[1]),cf[0],n); co.e[0] = cb.e[3]; co.e[1] = cc.e[3]; co.e[2] = cd[3]; co.e[3] = ce[3]; co.e[4] = cf[3]; co.e[5] = ca.e[3]; return co; } } /* END MakeCubeT */ Place_t GlueCubeT(a, b : Place_t) /* This procedure allows to glue two squared walls that is the union of two triangular walls. */ ta,Place_t tb[1+1]; { ta[0] = a; tb[0] = b; ta[1] = Clock(PrevE(PrevF(NextE(ta[0])))); tb[1] = Clock(PrevE(NextF(NextE(tb[0])))); assert(ta[1]!=a); assert(tb[1]!=b); Meld(tb[0], ta[0]); /* Update the edge slots for i==0 */ SetRingEdgeInfo(ta[0], PEdge(ta[0])); SetRingEdgeInfo(NextE(ta[0]), PEdge(NextE(ta[0]))); SetRingEdgeInfo(PrevE(ta[0]), PEdge(PrevE(ta[0]))); /* Update the cell slots for i==0 */ SetPneg(ta[0], PnegP(tb[0])); SetPneg(NextE(ta[0]), PnegP(NextE(tb[0]))); SetPneg(NextE(NextE(ta[0])), PnegP(NextE(NextE(tb[0])))); Meld(tb[1],ta[1]); /* Update the edge slots */ SetRingEdgeInfo(ta[1], PEdge(ta[1])); SetRingEdgeInfo(NextE(ta[1]), PEdge(NextE(ta[1]))); SetRingEdgeInfo(PrevE(ta[1]), PEdge(PrevE(ta[1]))); /* Update the cell slots */ SetPneg(ta[1], PnegP(tb[1])); SetPneg(NextE(ta[1]), PnegP(NextE(tb[1]))); SetPneg(NextE(NextE(ta[1])), PnegP(NextE(NextE(tb[1])))); return a; } /* END GlueCubeT */ PROCEDURE Make1DCubearray(uint order) : REF ARRAY OF @PLACES == /* Builds one row of cubes with order "order". */ VAR ca : REF SixPlaces_vec_t; cb : REF ARRAY OF @PLACES; { ca = SixPlaces_vec_new(order); cb = NEW(REF ARRAY OF @PLACES, order); for (i = 0; i < order; i++) { ca.e[i] = MakeCubeT(); cb.e[i,0] = ca.e[i,2]; cb.e[i,1] = ca.e[i,3]; cb.e[i,2] = ca.e[i,4]; cb.e[i,3] = ca.e[i,5]; } /* gluing */ for (j = 0; j < (order-1); j++) { GlueCubeT(NextE(PrevF(ca.e[j+1,4])),ca.e[j,0]); } return cb; } /* END Make1DCubearray */ Place_t MakeSausage(uint order) { ??? s = Make1DCubearray(order); { fprintf(stderr, " Building topology of sausage: \n"); return s[0,0]; } } /* END MakeSausage */ Place_t MakeTorus2D(uint order) { ??? s = Make1DCubearray(order); Place_t a = NextE(PrevF(s[0; with (2])), double b = Clock(PrevF(PrevE(NextF(NextF(NextE(PrevF(s[order-1,3]))))))) ){ GlueCubeT(a,b); fprintf(stderr, " Building topology of 2D Torus: \n"); return s[0,3]; } } /* END MakeTorus2D */ Place_t MakeTorus2H(uint order) /* Builds a solid torus with two holes. This construction is based in the connected sum of two manifolds: a!=b */ { ??? a = MakeTorus2D(order); ??? b = MakeTorus2D(order); Place_t c = NextF(NextE(NextF(NextF(NextE(PrevF(b)))))); { EVAL Triangulation.Glue(Clock(a),Clock(c),2); assert(Octf.DegreeOfWall(a) == 4); assert(Octf.DegreeOfWall(NextE(a)) == 7); assert(Octf.DegreeOfWall(PrevE(a)) == 4); fprintf(stderr, " Building topology of 2D Torus with two holes: \n"); return a; } } /* END MakeTorus2H */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp (o->shapeName, "torus2d"))) { o->shape = Shape_Torus2D } else if (0 == strcmp(o->shapeName, "torus2h"))){ o->shape = Shape_Torus2H } else if (0 == strcmp(o->shapeName, "sausage"))){ o->shape = Shape_Sausage } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n"); } argparser_get_keyword(pp, "-gridOrder"); o->gridOrder = argparser_get_next_int(pp, 3,30); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeObjectTriang \\\n" \ " -shape { torus2d | torus2h | sausage }\\\n" \ " -gridOrder \\\n"); END¦ } } return o; } /* END GetOptions */ PROCEDURE SetOrgAll(Place_t @p) /* Set alls places with the same origin that "a" (i.e with the @{node->?} {n}). */ void SetOrgAll(Place_t @p, Node_t n) Place_t t = a; VAR Place_t tn; { do { SetOrg(t,n); tn = Clock(PrevE(t)); do { SetOrg(tn,n); tn = NextF(tn); } while (!(( tn == Clock(PrevE(t))))); t = NextF(t); } while (t != a); } SetOrgAll; VAR Place_t an = a; Place_t ap = NextE(PrevF(PrevF(PrevE(a)))); { ??? n = Org(a); { do { SetOrgAll(an,n); an = ONext(an); } while (an != a); do { SetOrgAll(ap,n); ap = OPrev(ap); } while (!((ap == NextE(PrevF(PrevF(PrevE(a))))))); } } /* END SetOrgAll */ { Main(); } MakeObjectTriang. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakePentaOcta.c #define PROG_NAME "MakePentaOcta" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakePentaOcta_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program implements the automatic gluing of cells (tetrahedra, triangulated octahedra) for the 4D non-regular polytope: "Truncated Simplex", also know as: "PentaOcta". The Truncated Simplex has nv==10, ne==30, nf==30, np==10, self-dual. This 3D map is a polytope, but not a regular polytope, since it has 5 tetrahedral volumes and 5 octahedral volumes. */ #include #include // #INCLUDE // #INCLUDE // #INCLUDE TYPE double Row2I = ARRAY[0..1] OF uint; double z4_t = ARRAY[0..3] OF uint; typedef struct Options_t { bool_t detail; } CONST double INIT_STACK_SIZE = 700; cellnum == 45; VAR cell4 = NEW(REF ARRAY OF z4_t, INIT_STACK_SIZE); tetra : REF ARRAY OF ARRAY [0..3] OF Place_t; Options_t o; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Place_t GlueTetras(Ti,Tj,Ci,Cj: uint) /* Gluing the tetrahedra Ti with Tj through the free walls Ci and Cj respectively. */ void PrintInfo(case: uint;oi,oj,di,dj: uint) /* Prints information about the three possible cases in the gluing procedure. */ { fprintf(stderr, "case " & Fmt.Int(case) & ": "); fprintf(stderr, Fmt.Int(oi) & " " & Fmt.Int(di)&"\n"); fprintf(stderr, " "); fprintf(stderr, Fmt.Int(oj) & " " & Fmt.Int(dj)&"\n\n"); } PrintInfo; void UngluedInfo(ci,cj,ti,tj: uint) /* Prints information about unglued case in the gluing procedure. This procedure cause the halt of the program. */ { fprintf(stderr, "Not glue this case " & Fmt.Int(ci) & " " \ Fmt.Int(cj) & "\n"); fprintf(stderr, " Tetrahedra " & Fmt.Int(ti) & " " \ Fmt.Int(tj) & "\n"); Process.Exit¦(1); } UngluedInfo; { if (o->detail) { fprintf(stderr,"Ci=="&Fmt.Int(Ci)&" Cj=="&Fmt.Int(Cj)&", "); } IF /* 1 */ double Ci = 0) && (Cj == 0)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 2 */ double Ci = 0) && (Cj == 1)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 3 */ double Ci = 0) && (Cj == 2)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 4 */ double Ci = 0) && (Cj == 3)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 5 */ double Ci = 1) && (Cj == 0)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 6 */ double Ci = 1) && (Cj == 1)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 7 */ double Ci = 1) && (Cj == 2)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 8 */ double Ci = 1) && (Cj == 3)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 9 */ double Ci = 2) && (Cj == 0)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 10 */ double Ci = 2) && (Cj == 1)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 11 */ double Ci = 2) && (Cj == 2)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 12 */ double Ci = 2) && (Cj == 3)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 13 */ double Ci = 3) && (Cj == 0)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 14 */ double Ci = 3) && (Cj == 1)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 15 */ double Ci = 3) && (Cj == 2)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 16 */ double Ci = 3) && (Cj == 3)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } } return tetra[Ti].p[0]; } /* END GlueTetras */ void SetCornersTetra(uint Ti, z4_t row) /* Set the labels "row" in the tetrahedron Ti. */ { Node_t a = OrgV(tetra[Ti].p[0]); with ( double b = OrgV(Clock(tetra[Ti].p[0])); double c = OrgV(PrevE(tetra[Ti].p[1])); double d = OrgV(PrevE(tetra[Ti].p[0])) ){ a->num = row[0]; b->num = row[1]; c->num = row[2]; d->num = row[3]; } } SetCornersTetra; void SetGhostElementsS(Tuint i) /* Set one node, three @{edge->?}s and walls, such that the gluing of eigth tetrahedra, resemble an octahedron. This procedure set the upper tetrahedra. */ { Node_t v0 = OrgV(tetra[Ti].p[0]); with ( double e0 = PWedge(tetra[Ti].p[0]).edge; double e1 = PWedge(PrevE(tetra[Ti].p[0])).edge; double e2 = PWedge(PrevE(tetra[Ti].p[1])).edge; double f0 = PWedge(tetra[Ti].p[0]).wall; double f1 = PWedge(tetra[Ti].p[1]).wall; double f2 = PWedge(tetra[Ti].p[2]).wall ){ v0->exists = FALSE; e0->exists = FALSE; e1->exists = FALSE; e2->exists = FALSE; f0->exists = FALSE; f1->exists = FALSE; f2->exists = FALSE; } } SetGhostElementsS; void SetGhostElementsI(Tuint i) /* Set one node, three @{edge->?}s and walls, such that the gluing of eigth tetrahedra, resemble an octahedron. This procedure set the lower tetrahedra. */ { ??? v1 = OrgV(Clock(tetra[Ti; with (0])), double e0 = PWedge(tetra[Ti].p[0]).edge; double e1 = PWedge(NextE(tetra[Ti].p[0])).edge; double e2 = PWedge(NextE(tetra[Ti].p[1])).edge; double f0 = PWedge(tetra[Ti].p[0]).wall; double f1 = PWedge(tetra[Ti].p[1]).wall; double f2 = PWedge(tetra[Ti].p[3]).wall ){ v1->exists = FALSE; e0->exists = FALSE; e1->exists = FALSE; e2->exists = FALSE; f0->exists = FALSE; f1->exists = FALSE; f2->exists = FALSE; } } SetGhostElementsI; bool_t MustBeGlued(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have coherent orientations and must be glued. */ { Node_t a = OrgV(Ti)->num; Node_t ae = OrgV(NextE(Ti))->num; ??? ae_1 = OrgV(PrevE(Ti))->num; Node_t b = OrgV(Tj)->num; Node_t be = OrgV(NextE(Tj))->num; ??? be_1 = OrgV(PrevE(Tj))->num; { if (((a == b) && (ae == be) && (ae_1 == be_1) OR (a == b) && (ae == be_1) && (ae_1 == be))){ return TRUE; } return FALSE } } MustBeGlued; bool_t BadAttribution(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have incoherent orientations. */ { Node_t i0 = OrgV(Ti)->num; ??? i1 = OrgV(NextE(Ti))->num; ??? i2 = OrgV(PrevE(Ti))->num; Node_t j0 = OrgV(Tj)->num; ??? j1 = OrgV(NextE(Tj))->num; ??? j2 = OrgV(PrevE(Tj))->num; { if ((SpinBit(Ti)!=SpinBit(Tj))) { if (((i0 == j0) && (i1 == j2) && (i2 == j1) OR (i0 == j2) && (i1 == j1) && (i2 == j0) OR (i0 == j1) && (i1 == j0) && (i2 == j2) )){ return TRUE } }; if ((SpinBit(Ti) == SpinBit(Tj))) { if (((i0 == j0) && (i1 == j1) && (i2 == j2) OR (i0 == j2) && (i0 == j0) && (i2 == j1) OR (i0 == j1) && (i1 == j2) && (i2 == j0) )){ return TRUE } }; return FALSE } } BadAttribution; void PrintCorners(Tuint i) /* Print the corners of the triangular wall "Ti". */ { Node_t a = OrgV(walls[Ti])->num; Node_t ae = OrgV(NextE(walls[Ti]))->num; ??? ae_1 = OrgV(PrevE(walls[Ti]))->num; { fprintf(stderr, Fmt.Pad(Fmt.Int(a),3) & " " \ Fmt.Pad(Fmt.Int(ae),3) \ " " & Fmt.Pad(Fmt.Int(ae_1),3) & " "); } } PrintCorners; REF ARRAY OF EightPlaces_t poly ; id : uint = 0; count : uint = 1; walls : REF Place_vec_t; glues : REF ARRAY OF z4_t; { o = GetOptions(); poly = NEW(REF ARRAY OF EightPlaces_t,cellnum); tetra = NEW(REF ARRAY OF ARRAY [0..3] OF Place_t,cellnum); Place_vec_t walls = Place_vec_new( 4*cellnum); glues = NEW(REF ARRAY OF z4_t, 2*cellnum); /* Create topological tetrahedra */ for (i = 0; i < cellnum; i++) { poly[i] = MakeTetraTopo(1,1); } /* Create the tetrahedra */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { tetra[i].p[j] = poly[i,j]; assert(Ppos(tetra[i].p[j]) == NULL); } } /* cells with corners perfectly assigments */ /* the five first tetrahedra */ cell4[0] = (z4_t){{1,9,4,8}}; cell4[1] = (z4_t){{5,6,0,4}}; cell4[2] = (z4_t){{8,3,7,6}}; cell4[3] = (z4_t){{1,2,3,0}}; cell4[4] = (z4_t){{9,7,2,5}}; /* octahedron 1 */ cell4[5] = (z4_t){{101,9,7,8}}; SetGhostElementsS(5); cell4[6] = (z4_t){{101,9,8,4}}; SetGhostElementsS(6); cell4[7] = (z4_t){{101,9,4,5}}; SetGhostElementsS(7); cell4[8] = (z4_t){{101,9,5,7}}; SetGhostElementsS(8); cell4[9] = (z4_t){{6,101,7,8}}; SetGhostElementsI(9); cell4[10] = (z4_t){{6,101,8,4}}; SetGhostElementsI(10); cell4[11] = (z4_t){{6,101,4,5}}; SetGhostElementsI(11); cell4[12] = (z4_t){{6,101,5,7}}; SetGhostElementsI(12); /* octahedron 2 */ cell4[13] = (z4_t){{102,2,5,0}}; SetGhostElementsS(13); cell4[14] = (z4_t){{102,2,0,3}}; SetGhostElementsS(14); cell4[15] = (z4_t){{102,2,3,7}}; SetGhostElementsS(15); cell4[16] = (z4_t){{102,2,7,5}}; SetGhostElementsS(16); cell4[17] = (z4_t){{6,102,5,0}}; SetGhostElementsI(17); cell4[18] = (z4_t){{6,102,0,3}}; SetGhostElementsI(18); cell4[19] = (z4_t){{6,102,3,7}}; SetGhostElementsI(19); cell4[20] = (z4_t){{6,102,7,5}}; SetGhostElementsI(20); /* octahedron 3 */ cell4[21] = (z4_t){{103,9,2,5}}; SetGhostElementsS(21); cell4[22] = (z4_t){{103,9,5,4}}; SetGhostElementsS(22); cell4[23] = (z4_t){{103,9,4,1}}; SetGhostElementsS(23); cell4[24] = (z4_t){{103,9,1,2}}; SetGhostElementsS(24); cell4[25] = (z4_t){{0,103,2,5}}; SetGhostElementsI(25); cell4[26] = (z4_t){{0,103,5,4}}; SetGhostElementsI(26); cell4[27] = (z4_t){{0,103,4,1}}; SetGhostElementsI(27); cell4[28] = (z4_t){{0,103,1,2}}; SetGhostElementsI(28); /* octahedron 4 */ cell4[29] = (z4_t){{104,9,2,1}}; SetGhostElementsS(29); cell4[30] = (z4_t){{104,9,1,8}}; SetGhostElementsS(30); cell4[31] = (z4_t){{104,9,8,7}}; SetGhostElementsS(31); cell4[32] = (z4_t){{104,9,7,2}}; SetGhostElementsS(32); cell4[33] = (z4_t){{3,104,2,1}}; SetGhostElementsI(33); cell4[34] = (z4_t){{3,104,1,8}}; SetGhostElementsI(34); cell4[35] = (z4_t){{3,104,8,7}}; SetGhostElementsI(35); cell4[36] = (z4_t){{3,104,7,2}}; SetGhostElementsI(36); /* octahedron 5 */ cell4[37] = (z4_t){{105,1,0,4}}; SetGhostElementsS(37); cell4[38] = (z4_t){{105,1,4,8}}; SetGhostElementsS(38); cell4[39] = (z4_t){{105,1,8,3}}; SetGhostElementsS(39); cell4[40] = (z4_t){{105,1,3,0}}; SetGhostElementsS(40); cell4[41] = (z4_t){{6,105,0,4}}; SetGhostElementsI(41); cell4[42] = (z4_t){{6,105,4,8}}; SetGhostElementsI(42); cell4[43] = (z4_t){{6,105,8,3}}; SetGhostElementsI(43); cell4[44] = (z4_t){{6,105,3,0}}; SetGhostElementsI(44); /* set the labels for each tetrahedra */ for (i = 0; i < cellnum; i++) { SetCornersTetra(i,cell4[i]); } /* builds the table of walls for choose which tetrahedra must be gluing. */ if (o->detail) { fprintf(stderr, "C id table wall\n"); fprintf(stderr, "-------------------------\n"); } for (i = 0; i < cellnum; i++) { if (o->detail) { fprintf(stderr, Fmt.Int(i) & "\n"); } for (k = 0; k < 4; k++) { walls[(4*i)+k] = tetra[i].p[k]; if (o->detail) { fprintf(stderr," "& Fmt.Pad(Fmt.Int(id),4)&" "); id++; PrintCorners((4*i)+k); fprintf(stderr, " " & Fmt.Int(k) & "\n"); } } } /* computing which cells must be gluing. */ for(k = 0; k < walls.ne; k++) { for (l = k+1 TO LAST(walls^)) { for (m = 0; m < 3; m++) { ??? e = NextEK(walls[l],m); with ( ){ if ((MustBeGlued(walls[k],e))) { if (o->detail) { fprintf(stderr, Fmt.Int(count) & "\n"); fprintf(stderr, "must be gluing: walls[" & Fmt.Int(k) \ "] with "); fprintf(stderr, "walls[" & Fmt.Int(l) &"]\n"); } ??? kc = k % 4; ??? kt = k DIV 4; ??? lc = l % 4; ??? lt = l DIV 4; { if (o->detail) { fprintf(stderr, " tetra["&Fmt.Int(kt) & "," \ Fmt.Int(kc) & "] and tetra[" & Fmt.Int(lt) & "," \ Fmt.Int(lc) & "]\n\n"); } glues[count-1] = (z4_t){{kt,lt,kc,lc}}; count++; if ((BadAttribution(walls[k],e))) { fprintf(stderr, "Bad Attribution " & " tetra["& Fmt.Int(kt) &"and tetra[" & Fmt.Int(lt) & "]\n"); } } } } } } } /* Do the automatic gluing of tetrahedra */ for (i = 0; i < 2*cellnum; i++) { ??? c = glues[i]; { EVAL GlueTetras(c[0],c[1],c[2],c[3]); } } /* Set the origins. */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { ??? a = tetra[i].p[j]; with ( double b = NextE(a); double c = PrevE(a) ){ SetOrgAll(a,OrgV(a)); SetOrgAll(b,OrgV(b)); SetOrgAll(c,OrgV(c)); } } } /* Builds and writes the topology. */ fprintf(stderr, "Building the topology of pentaocta:\n"); ??? a = tetra[44; with (0], double top = MakeElemTable(a); double c = GenCoords(top)^; double shapeName = "pentaocta" ){ /* seting the elements root for edges and walls.*/ for (i = 0; i < top.wall.ne; i++) { ??? f = top.wall[i]; { f->root = f->num; } } for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i]; { e->root = e->num; } } /* test for the original elements */ VAR nve,nee,nfe: uint = 0; { for (i = 0; i < top.node.ne; i++) { ??? v = top.node[i]; { if (v->exists){ nve++; } } } for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i]; { if (e->exists){ nee++; } } } for (i = 0; i < top.wall.ne; i++) { ??? f = top.wall[i]; { if (f->exists){ nfe++; } } } assert(nve == 10); assert(nee == 30); assert(nfe == 30); } WriteTopology(shapeName, top, "Created by MakePentaOcta: " & shapeName & ".tp on " \ Today()); WriteMaterials(shapeName, top, "Created by MakePentaOcta: " & shapeName & ".ma on " \ Today()); WriteState(shapeName, top, c, "Created by MakePentaOcta: " & shapeName & ".st on " \ Today() &"\nRandom Geometry"); } } DoIt; /* UNUSED */ PROCEDURE PrintRow4I(m: z4_t) /* Print an array of four integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & " " \ Fmt.Int(m[2]) & " " & Fmt.Int(m[3]) & "\n"); } /* END PrintRow4I */ /* UNUSED */ PROCEDURE PrintRow2I(m: Row2I) /* Print an array of two integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & "\n"); } /* END PrintRow2I */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY o->detail = argparser_keyword_present(pp, "-detail"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakePentaOcta [ -detail ] \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } MakePentaOcta. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakePolytope.c #define PROG_NAME "MakePolytope" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakePolytope_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program generates the topology of 4D regular and convex polytopes (".tp" files) with fixed ("-fix") or random ("-ran") geometry. */ #define MakePolytope_C_author \ "Implemented by L.A.P.Lozada, 1999-2000.\n" \ "Modified by L.A.P.Lozada on 2000-02-10." // #INCLUDE // #INCLUDE #include // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include TYPE double Shape_t = {cell5, cell8, cell16}; typedef struct Options_t { Shape_t shape; char *shapeName; bool_t random; /* TRUE if it geometry is random. */ bool_t polyroot; /* includes the cell root information */ } CONST double order = 1; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Coords_t c; char *tag; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? ran = o->random; ??? m = MakePolytope(o->shape); ??? top = MakeElemTable(m); { c = r4_vec_new(top.node.ne); /* seting the elements root for edges and walls.*/ for (i = 0; i < top.wall.ne; i++) { Wall_t f = top.wall.e[i]; f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = top.edge.e[i]; e->root = e->num; } if (! ran ){ c = FixCoords(top, o->shape, m); tag ="-fix"; WriteTopology( o->shapeName & tag, top, "Created by MakePolytope: " & o->shapeName & "-fix.tp on " \ Today() ); WriteState( o->shapeName & tag,top, c^, "Created by MakePolytope: " & o->shapeName & "-fix.st on " \ Today() ); WriteMaterials( o->shapeName & tag, top, "Created by MakePolytope: " & o->shapeName & "-fix.ma on " \ Today() ); } else { c = GenCoords(top); tag ="-r"; WriteTopology( o->shapeName & tag, top, "Created by MakePolytope: " & o->shapeName & "-r.tp on " \ Today() ); WriteState( o->shapeName & tag,top, c^, "Created by MakePolytope: " & o->shapeName & "-r.st on " \ Today() & "\nRandom Geometry" ); if (! o->polyroot) { WriteMaterials( o->shapeName & tag, top, "Created by MakePolytope: " & o->shapeName & "-r.ma on " \ Today(), FALSE); } else if (o->polyroot){ for (i = 0; i < top.cell.ne; i++) { ??? p = top.cell[i]; { p->root = p->num; } } WriteMaterials( o->shapeName & tag, top, "Created by MakePolytope: " & o->shapeName & "-r.ma on " \ Today(), TRUE); } } return 0; } Place_t MakePolytope(Shape_t shape) { CASE shape OF break; case Shape_cell5: return MakeHypertetrahedron(); break; case Shape_cell8: return MakeHypercube(); break; case Shape_cell16: return MakeHyperoctahedron(); } } /* END MakePolytope */ /* Shape builders: */ Place_t MakeHypertetrahedron() /* Glue five tetrahedra. The Hypertetrahedron is one polytope that corresponding to analogus 4-D of one 3-simplex. This 4-simplex have C5,0 nodes, C5,1 edegs, C5,2 walls and C5,3 cells. */ { ??? o = order; ??? a = MakeTetraTopo(o; with (o), double b = MakeTetraTopo(o,o); double c = MakeTetraTopo(o,o); double d = MakeTetraTopo(o,o); double e = MakeTetraTopo(o,o) ){ Glue(Spin(b[1]), a[0],o); /* a-b, 0-1 */ Glue(Spin(a[1]), c[0],o); /* a-c, 0-2 */ Glue(Spin(c[1]), b[0],o); /* b-c, 1-2 */ Glue(Spin(a[3]), e[2],o); /* a-e, */ Glue(Clock(a[2]),d[2],o); /* a-d */ Glue(Clock(d[3]),e[3],o); /* d-e */ Glue(Spin(PrevE(d[0])),NextE(c[2]),o); /* c-d */ Glue(Clock(PrevE(b[2])),PrevE(d[1]),o); /* d-b */ Glue(Spin(PrevE(e[1])),NextE(c[3]),o); /* e-c */ Glue(Clock(PrevE(b[3])),PrevE(e[0]),o); /* e-b */ fprintf(stderr, "Building topology of 5-cell:\n"); return b[1]; } } /* END MakeHypertetrahedron */ Place_t MakeHyperoctahedron() /* Glue 16 tetrahedra. The Hyperoctahedron is one polytope that corresponding to analogus 4-D of one octahedron. This politope is the dual of the hipercube, so has 8 nodes, 24 @{edge->?}s, 32 walls and 16 tetraedra. */ { ??? o = 4; ??? a = MakeTetraTopo(o; with (o) ){ Glue(Spin(a[1]),a[0],o); Glue(Spin(a[3]),a[2],o); fprintf(stderr, "Building topology of Hyperoctahedron:\n"); return a[1]; } } /* END MakeHyperoctahedron */ Place_t MakeHypercube() /* Glue eight cubes. The Hypercube is one polytope that corresponding to analogus 4-D of one cube. This polytope have "16" nodes, "32" @{edge->?}s, "24" walls, "96" wedges and "8" cells. */ { ??? ca = MakeCube(); ??? cb = MakeCube(); ??? cc = MakeCube(); ??? cd = MakeCube(); ??? ce = MakeCube(); ??? cf = MakeCube(); ??? cg = MakeCube(); ??? ch = MakeCube(); { /* step one */ GlueCube(ca.e[1], PrevF(cb.e[2])); /* 1, a-b */ GlueCube(ca.e[2], PrevF(cc.e[3])); /* 2, a-c */ GlueCube(ca.e[3], PrevF(cd[4])); /* 3, a-d */ GlueCube(ca.e[4], PrevF(ce[1])); /* 4, a-e */ GlueCube(ca.e[5], Clock(cf[0])); /* 5, a-f */ GlueCube(ca.e[0], Clock(cg[5])); /* 6, a-g */ GlueCube(cg[0], Clock(ch[5])); /* 7, g-h */ /* step two */ GlueCube(cb.e[2], PrevF(cc.e[4])); /* 8, b-c */ GlueCube(cc.e[3], PrevF(cd[1])); /* 9, c-d */ GlueCube(cd[4], PrevF(ce[2])); /* 10, d-e */ GlueCube(ce[1], PrevF(cb.e[3])); /* 11, e-b */ GlueCube(NextE(cb.e[5]), Clock(PrevE(cf[1]))); /* 12, f-b */ GlueCube(ce[5], Clock(PrevE(cf[4]))); /* 13, f-e */ GlueCube(NextE(NextE(cc.e[5])), PrevF(cf[0])); /* 14, f-c */ GlueCube(PrevE(cf[3]), Clock(PrevE(cd[5]))); /* 15, f-d */ GlueCube(PrevE(cb.e[0]), Clock(NextE(cg[1]))); /* 16, b-g */ GlueCube(ce[0], Clock(NextE(cg[4]))); /* 17, e-g */ GlueCube(NextE(cg[3]), Clock(NextE(cd[0]))); /* 18, d-g */ GlueCube(NextE(cg[2]),Clock(PrevE(PrevE(cc.e[0]))));/* 19, c-g */ /* step three */ GlueCube(cb.e[1], Clock(ch[1])); /* 20, b-h */ GlueCube(ch[2], Clock(cc.e[2])); /* 21, c-h */ GlueCube(PrevE(cd[3]), Clock(NextE(ch[3]))); /* 22, d-h */ GlueCube(PrevE(ce[4]), Clock(NextE(ch[4]))); /* 23, e-h */ GlueCube(cf[5],Clock(ch[0])); /* 24, f-h */ fprintf(stderr, "Building topology of 8-cell:\n"); return ch[0]; } } /* END MakeHypercube */ /* UNUSED */ Place_t Make24tetra() a : ARRAY[0..23] OF ARRAY[0..7] OF Place_t; { for (i = 0; i <= (23); i++){ a[i] = MakeTetraTopo(order,order); } /* first level */ Glue(Spin(a[1][1]),a[0][0],order); Glue(Spin(a[2][1]),a[1][0],order); Glue(Spin(a[3][1]),a[2][0],order); Glue(Spin(a[4][1]),a[3][0],order); Glue(Spin(a[5][1]),a[4][0],order); Glue(Spin(a[0][1]),a[5][0],order); /* next level */ Glue(Spin(a[0][3]),a[6][2],order); Glue(Spin(a[1][3]),a[7][2],order); Glue(Spin(a[2][3]),a[8][2],order); Glue(Spin(a[3][3]),a[9][2],order); Glue(Spin(a[4][3]),a[10][2],order); Glue(Spin(a[5][3]),a[11][2],order); Glue(Spin(a[12][1]),a[6][0],order); Glue(Spin(a[7][1]),PrevE(a[12][7]),order); Glue(Spin(a[13][1]),a[7][0],order); Glue(Spin(a[8][1]),PrevE(a[13][7]),order); Glue(Spin(a[14][1]),a[8][0],order); Glue(Spin(a[9][1]),PrevE(a[14][7]),order); Glue(Spin(a[15][1]),a[9][0],order); Glue(Spin(a[10][1]),PrevE(a[15][7]),order); Glue(Spin(a[16][1]),a[10][0],order); Glue(Spin(a[11][1]),PrevE(a[16][7]),order); Glue(Spin(a[17][1]),a[11][0],order); Glue(Spin(a[6][1]),PrevE(a[17][7]),order); /* Last level */ Glue(Spin(NextE(a[12][0])),a[18][2],order); Glue(Spin(NextE(a[13][0])),a[19][2],order); Glue(Spin(NextE(a[14][0])),a[20][2],order); Glue(Spin(NextE(a[15][0])),a[21][2],order); Glue(Spin(NextE(a[16][0])),a[22][2],order); Glue(Spin(NextE(a[17][0])),a[23][2],order); Glue(Spin(a[19][1]),a[18][0],order); Glue(Spin(a[20][1]),a[19][0],order); Glue(Spin(a[21][1]),a[20][0],order); Glue(Spin(a[22][1]),a[21][0],order); Glue(Spin(a[23][1]),a[22][0],order); Glue(Spin(a[18][1]),a[23][0],order); fprintf(stderr, "Building topology of Icosahedron: \n"); return a[0][1]; } /* END Make24tetra */ Coords_t *FixCoordsHypercube( Place_t *h; *ElemTableRec_t *top; )== { ??? r = NEW(REF Coords_t; with ( top->node.ne), double c = r^; double o1 = (r4_t){ 1.0, 1.0, 1.0,1.0}; double o2 = (r4_t){ 1.0, 1.0,-1.0,1.0}; double o3 = (r4_t){ 1.0,-1.0, 1.0,1.0}; double o4 = (r4_t){ 1.0,-1.0,-1.0,1.0}; double o5 = (r4_t){-1.0, 1.0, 1.0,1.0}; double o6 = (r4_t){-1.0, 1.0,-1.0,1.0}; double o7 = (r4_t){-1.0,-1.0, 1.0,1.0}; double o8 = (r4_t){-1.0,-1.0,-1.0,1.0}; double o9 = (r4_t){ 1.0, 1.0, 1.0,-1.0}; o10== (r4_t){ 1.0, 1.0,-1.0,-1.0}, o11== (r4_t){ 1.0,-1.0, 1.0,-1.0}, o12== (r4_t){ 1.0,-1.0,-1.0,-1.0}, o13== (r4_t){-1.0, 1.0, 1.0,-1.0}, o14== (r4_t){-1.0, 1.0,-1.0,-1.0}, o15== (r4_t){-1.0,-1.0, 1.0,-1.0}, o16== (r4_t){-1.0,-1.0,-1.0,-1.0} ){ void SetCoCoords(Place_t e, r4_t *cv) { c[OrgV(e)->num] = cv; } SetCoCoords; { /* Set the corners */ SetCoCoords(h,o13); SetCoCoords(PrevE(h),o15); SetCoCoords(PrevE(PrevE(h)),o11); SetCoCoords(Clock(h),o9); SetCoCoords(PrevE(PrevF(h)),o14); SetCoCoords(PrevE(PrevE(PrevF(h))),o10); SetCoCoords(PrevE(PrevF(PrevE(PrevE(h)))),o12); SetCoCoords(PrevE(PrevE(PrevF(PrevE(PrevE(h))))),o16); SetCoCoords(PrevE(NextF(h)),o5); SetCoCoords(NextE(NextE(NextF(h))),o1); SetCoCoords(PrevE(NextF(PrevE(PrevE(h)))),o3); SetCoCoords(PrevE(PrevE(NextF(PrevE(PrevE(h))))),o7); SetCoCoords(PrevE(PrevF(PrevE(PrevE(PrevF(h))))),o2); SetCoCoords(PrevE(PrevE(PrevF(PrevE(PrevE(PrevF(h)))))), o6); SetCoCoords(PrevE(PrevF(PrevE(PrevE(PrevF(PrevE(PrevE (h))))))),o8); SetCoCoords(PrevE(PrevE(PrevF(PrevE(PrevE(PrevF(PrevE (PrevE(h)))))))),o4); } return r; } } /* END FixCoordsHypercube */ PROCEDURE FixCoordsHypertetrahedron( /* UNUSED */ *h: Place_t; *ElemTableRec_t *top; ): REF Coords_t { ??? r = NEW(REF Coords_t; with ( top->node.ne), double c = r^; double c0 = (r4_t){0.0, 0.0, 0.0, 2.0}; double c1 = (r4_t){-1.118030, 1.118030, 1.118030, -0.50}; double c2 = (r4_t){ 1.118030, -1.118030, 1.118030, -0.50}; double c3 = (r4_t){ 1.118030, 1.118030, -1.118030, -0.50}; double c4 = (r4_t){-1.118030, -1.118030, -1.118030, -0.50} ){ c[0] = c0; c[1] = c1; c[2] = c2; c[3] = c3; c[4] = c4; return r; } } /* END FixCoordsHypertetrahedron */ PROCEDURE FixCoordsHyperoctahedron( /* UNUSED */ *h: Place_t; *ElemTableRec_t *top; ): REF Coords_t { ??? r = NEW(REF Coords_t; with ( top->node.ne), double c = r^; double c0 = (r4_t){ 0.0, -2.0, 0.0, 0.0}; double c1 = (r4_t){ 0.0, 0.0, -2.0, 0.0}; double c2 = (r4_t){ 2.0, 0.0, 0.0, 0.0}; double c3 = (r4_t){ 0.0, 0.0, 0.0,-2.0}; double c4 = (r4_t){ 0.0, 0.0, 2.0, 0.0}; double c5 = (r4_t){ 0.0, 0.0, 0.0, 2.0}; double c6 = (r4_t){-2.0, 0.0, 0.0, 0.0}; double c7 = (r4_t){ 0.0, 2.0, 0.0, 0.0} ){ c[0] = c0; c[1] = c1; c[2] = c2; c[3] = c3; c[4] = c4; c[5] = c5; c[6] = c6; c[7] = c7; return r; } } /* END FixCoordsHyperoctahedron */ Coords_t *FixCoords(ElemTableRec_t *top, shape:Shape_t; *m : Place_t)== { ??? r = NEW(REF Coords_t; with ( top->node.ne), double c = r^ ){ if (shape == Shape_cell5 ){ /* Atribui coordenadas fixas no R4, t. q. o comprimento de toda aresta \'e 1.5811. */ c = FixCoordsHypertetrahedron(m,top)^; } else if ( shape == Shape_cell8){ /* Atribui coordenadas fixas no R4, t. q. o comprimento de toda aresta \'e 2.00. */ c = FixCoordsHypercube(m,top)^; } else if ( shape == Shape_cell16){ /* Atribui coordenadas fixas no R4. */ c = FixCoordsHyperoctahedron(m,top)^; } return r; } } /* END FixCoords */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "5cell"))) { o->shape = Shape_cell5 } else if (0 == strcmp(o->shapeName, "8cell"))){ o->shape = Shape_cell8 } else if (0 == strcmp(o->shapeName, "16cell"))){ o->shape = Shape_cell16 } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } o->random = argparser_keyword_present(pp, "-random"); o->polyroot = argparser_keyword_present(pp, "-polyroot"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakePolytope \\\n" \ " -shape { 5cell | 8cell | 16cell ... } \\\n" \ " [ -random ] [-polyroot]\n"); END¦ } } return o; } /* END GetOptions */ /* end MakePolytope */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeRawTetra.c #define PROG_NAME "MakeRawTetra" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeRawTetra_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Creates ".tp",".tb",".st" and ".ma" files for one topological tetrahedron of order "gridOrder" with fixed geometry. The nodes of a individually tetra- hedron ("gridOrder == 1") of side length Sqrt(2) be given by a particulary form when the nodes are taken as corners of a cube. One such tetrahedron for a cube of side length 1 gives the tetrahedron of side length Sqrt(2) having nodes: (0,0,0,0), (0,1,1,0), (1,0,1,0), (1,1,0.0). Every topological tetraedron have eight places "corners" associa- ted to hin. Let "a" one @place of Interface "Triangulation", so we associate the node (0,0,0,0) to "ca.e[0]"; (1,0,1,0) to "ca.e[2]"; (0,1,1,0) to "ca.e[4]" and the node (1,1,0,0) to "ca.e[6]". */ // #INCLUDE // #INCLUDE #include // #INCLUDE #include #include #include // // #INCLUDE // Coords_t, OrgV, Place_t, Topology, EmphasizeTetrahedron; // #INCLUDE // NextE, Clock, PrevE, NextF; TYPE typedef struct Options_t { uint gridOrder; } PROCEDURE Main() { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? ca = MakeTetraTopo(o->gridOrder; with (o->gridOrder), top == MakeElemTable(ca.e[1]), c == ComputeCoordinates(ca, top, o->gridOrder)^, co == "\nIndividual topological tetrahedron with fixed geometry\n" & "Created by MakeRawTetra: tetraf-" & Fmt.Int(o->gridOrder), double name = "tetra-fixed" ){ EmphasizeTetrahedron(ca.e[0], ca.e[3], o->gridOrder); /* Set the root elements */ for (i = 0; i < top.wall.ne; i++) { Wall_t f = top.wall.e[i]; f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = top.edge.e[i]; e->root = e->num; } WriteTopology( name & "-" & Fmt.Int(o->gridOrder), top, co & ".tp on " & Today()); /* WriteTable( name & "-" & Fmt.Int(o->gridOrder), top, co & ".tb on " & Today()); */ WriteState( name & "-" & Fmt.Int(o->gridOrder), top, c, co & ".st on "& Today()); WriteMaterials( name & "-" & Fmt.Int(o->gridOrder), top, co & ".ma on " & Today()); } } /* END Main */ Coords_t *ComputeCoordinates( *Place_t ca.e[7+1]; *ElemTableRec_t *top; uint order; )== { ??? r = NEW(REF Coords_t; with ( top->node.ne), double c = r^; double o1 = (r4_t){0.0,0.0,0.0,0.0}, /* the node (0,0,0,0) */ double o2 = (r4_t){1.0,0.0,1.0,0.0}, /* the node (1,0,1,0) */ double o3 = (r4_t){0.0,1.0,1.0,0.0}, /* the node (0,1,1,0) */ double o4 = (r4_t){1.0,1.0,0.0,0.0} /* the node (1,1,0,0) */ ){ void SetCornerCoords(Place_t e, r4_t *cv) { c[OrgV(e)->num] = cv; } SetCornerCoords; void SetCoordinatesPrimal(Place_t @p, *o: r4_t) /* Set the node coordinates along the primal @{edge->?} of topological tetrahedron. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0], o[1]+x, o[2]+x, o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a,FLOAT(i,double)*1.0/FLOAT(order,double)); } } SetCoordinatesPrimal; void SetCoordinatesDual(Place_t @p, *o: r4_t) /* Set the node coordinates along the dual @{edge->?} of topological tetrahedron. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0], o[1]+x, o[2]-x, o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a,FLOAT(i,double)*1.0/FLOAT(order,double)); } } SetCoordinatesDual; { /* Set the corners */ SetCornerCoords(ca.e[0],o1); SetCornerCoords(ca.e[3],o2); SetCornerCoords(ca.e[4],o3); SetCornerCoords(ca.e[6],o4); SetCoordinatesPrimal(ca.e[0], o1); SetCoordinatesDual(ca.e[3], o2); } return r; } } /* END ComputeCoordinates */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-gridOrder"); o->gridOrder = argparser_get_next_int(pp, 1, 20); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeRawTetra -gridOrder \n"); END¦ } } return o; } /* END GetOptions */ { Main(); } MakeRawTetra. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/MakeVStar.c #define PROG_NAME "MakeVStar" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MakeVStar_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Generates ".tp",".tb",".ma" and ".st" files for some simples, triangulated and regular Cells in R^{4}. The node coordinates are random numbers in [-1..+1]. */ #include // #INCLUDE /* !!! Used to import instead of */ #include // #INCLUDE // #INCLUDE // #INCLUDE #include // #INCLUDE TYPE Shape_t == { sh_4_vstar, sh_8_vstar, sh_20_vstar, sh_60_vstar }; typedef struct Options_t { Shape_t shape; char *shapeName; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakePoly(o->shape); ??? top = MakeElemTable(m); Coords_t c = GenCoords(&top);; { /* Set the "root" attribute for walls and edges. */ for (i = 0; i < top.wall.ne; i++) { Wall_t f = top.wall.e[i]; f->root = f->num; } for (i = 0; i < top.edge.ne; i++) { Edge_t e = top.edge.e[i]; e->root = e->num; } SetElemProperties(top); WriteTopology(o->output, tag, &top, topo_cmt); // shapeName MakeVStar shapeName WriteState( o->shapeName, top, c,"Created by MakeVStar: " & o->shapeName \ ".st on " & Today() & "\nRandom Geometry" ); WriteMaterials(o->output, tag, &top, topo_cmt); // shapeName MakeVStar shapeName return 0; } Place_t MakePoly(Shape_t shape) { CASE shape OF break; case Shape_sh_4_vstar: return Make_4_vstar(); break; case Shape_sh_8_vstar: return Make_8_vstar(); break; case Shape_sh_20_vstar: return Make_20_vstar(); break; case Shape_sh_60_vstar: return Make_60_vstar(); } } /* END MakePoly */ /* Shape_t builders: */ Place_t Make_4_vstar() { fprintf(stderr, "Building topology of 4_vstar" & "\n"); return VStar.MakeTetrahedronTriang()[0]; } /* END Make_4_vstar */ Place_t Make_20_vstar() { fprintf(stderr, "Building Topology of an 20_vstar: \n"); ??? ico = VStar.MakeIcosahedronTriang(); { return ico.e[10]; } } /* END Make_20_vstar */ Place_t Make_8_vstar() { fprintf(stderr, "Building Topology of an 8_vstar: \n"); ??? oct = VStar.MakeOctahedronTriang() /* true for emphasize the origial elements */; { return oct[0]; } } /* END Make_8_vstar */ Place_t Make_60_vstar() { ??? dode = VStar.MakeDodecahedronTriang() /* true for emphasize the origial elements */; { /* safety tests */ for (i = 0; i < 12; i++) { ??? a = dode[i; with (0] DO if ((SpinBit(a) == 0)) { for (j = 1; j < 5; j++) { assert(dode[i,j] == Clock(NextE(NextF(PrevE(dode[i,j-1]))))); } assert(dode[i,0] == Clock(NextE(NextF(PrevE(dode[i,4]))))); } else if ((SpinBit(a) == 1)){ for (j = 1; j < 5; j++) { assert(dode[i,j] == Clock(PrevE(NextF(NextE(dode[i,j-1]))))); } assert(dode[i,0] == Clock(PrevE(NextF(NextE(dode[i,4]))))); } } } /* end safety tests */ fprintf(stderr, "Building topology of an 60_vstar (version 1): \n"); return dode[11,0]; } } /* END Make_60_vstar */ /* Procedures to set element properties */ PROCEDURE SetElemProperties(ElemTableRec_t *top) Place_t *b; { for (i = 0; i < top->node.ne; i++){ SetNodeProperties(top->node[i], border = FALSE); } for (i = 0; i < top->NE; i++){ SetEdgeProperties(top->edge[i].pa, border = FALSE); } for (i = 0; i < top->wall.ne; i++) { SetWallProperties(top->wall[i].pa, border = FALSE); ??? a = top->wall[i].pa; { if (((Ppos(a) == NULL)) || ((Pneg(a) == NULL))) { SetWallProperties(a, TRUE); SetNodeProperties(a, border = TRUE); SetEdgeProperties(a, border = TRUE); b = a; do { SetNodeProperties(b, border = TRUE); SetEdgeProperties(b, border = TRUE); b = NextE(b) } while (b != a); } } } } /* END SetElemProperties */ PROCEDURE SetWallProperties(Place_t b, bool_t border) /* Set wall properties according to internal/border. */ { ??? t = NARROW(PWall(b); with ( Triangulation.Wall) ){ if (border) { t.color = (frgb_t){1.00, 0.75, 0.20}; t.transp = (frgb_t){0.90, 0.90, 0.90}; } else { t.color = (frgb_t){0.90, 1.00, 0.20}; t.transp = (frgb_t){0.95, 0.95, 0.95}; } } } /* END SetWallProperties */ PROCEDURE SetEdgeProperties(Place_t @p, bool_t border) /* Set the material proeprties for an @{edge->?} according to internal/border. */ { ??? e = NARROW(PEdge(a), Triangulation.edge); with ( ){ if (border) { e.color = (frgb_t){0.000, 0.000, 0.000}; e.transp = (frgb_t){0.000, 0.000, 0.000}; e.radius = 0.0075 } else { e.color = (frgb_t){0.333, 0.333, 0.333}; e.transp = (frgb_t){0.000, 0.000, 0.000}; e.radius = 0.0050; } } } /* END SetEdgeProperties */ PROCEDURE SetNodeProperties(Place_t @p, bool_t border) /* Set the node material properties. */ { Node_t v = OrgV(a); { if (border) { v.radius = 0.015; v.color = (frgb_t){0.000, 0.000, 0.000} } else { v.radius = 0.025; v.color = (frgb_t){0.333, 0.333, 0.333} } } } /* END SetNodeProperties */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "4-vstar") )) { o->shape = Shape_sh_4_vstar } else if (0 == strcmp(o->shapeName, "8-vstar"))){ o->shape = Shape_sh_8_vstar } else if (0 == strcmp(o->shapeName, "20-vstar"))){ o->shape = Shape_sh_20_vstar } else if (0 == strcmp(o->shapeName, "60-vstar"))){ o->shape = Shape_sh_60_vstar } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeVStar \\\n" \ " -shape { 4-vstar | 8-vstar | 20-vstar | 60-vstar }\n"); END¦ } } return o; } /* END GetOptions */ /* end MakeVStar */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/TestTopology.c #define PROG_NAME "TestTopology" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestTopology_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program to test the characteristics of the Star and Link for all node, as well as, if every node is internal and if every wall if internal (The input file must be contain one Triangulation not degene- rate. Also include some procedures for tests if every cell on the star for one node are differents as well as every cell is contained on the list of cell of ".tp" topology.. */ #define TestTopology_C_author \ "Created by L. P. Lozada, 1999-2000\n" \ "Modified by L.A.P.Lozada on 99-08-27." #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // #INCLUDE TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ bool_t listStar; /* For enumerate the cell list belong of the star for every node. */ } /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ TYPE double Place_t = TriangulationPlace_t; double Tri = ARRAY [0..2] OF uint; double EndPoint = ARRAY [0..1] OF uint; double Bi = ARRAY [0..2] OF EndPoint; double Node = Triangulation.Node; /* UNUSED */ INTEGER Order(char *name) <* FATAL FloatMode.Trap, Lex.Error); { ??? n = Text.FindChar(name; with ( '-'), double o = Scan.Int(Text.Sub(name, n+1, 2)) ){ return o; } } /* END Order */ /* UNUSED */ PROCEDURE TestePolyDif(ElemDataRec_t *top) p,q : REF ARRAY OF INTEGER; { for (i = 0; i < top->node.ne; i++){ ??? a = top->node[i]; ??? poly = Triangulation.StarOfNode(a; with (top) ){ for(j = 0; j < poly.ne; j++) { p = NEW(REF ARRAY OF INTEGER, 4); p[0] = poly[j][0]->num; p[1] = poly[j][1]->num; p[2] = poly[j][2]->num; p[3] = poly[j][3]->num; Mis.InsertionSort(3,p); for (i = j+1 TO LAST(poly^)) { q = NEW(REF ARRAY OF INTEGER, 4); q[0] = poly[i][0]->num; q[1] = poly[i][1]->num; q[2] = poly[i][2]->num; q[3] = poly[i][3]->num; Mis.InsertionSort(3,q); if ((p[0]==q[0]) && (p[1]==q[1]) && (p[2]==q[2]) && ((p[3]==q[3]) )){ fprintf(stderr, "ERRO ESTA NA LISTA<====\n"); } } } } } } /* END TestePolyDif */ /* UNUSED */ PROCEDURE TestePolyExist(ElemDataRec_t *top) bool_t saiu = FALSE; p : REF ARRAY OF INTEGER; { /* realiza teste si poliedro esta na lista */ for (i = 0; i < top->node.ne; i++) { ??? a = top->node[i]; ??? poly = Triangulation.StarOfNode(a; with (top) ){ for(j = 0; j < poly.ne; j++) { p = NEW(REF ARRAY OF INTEGER, 4); p[0] = poly[j][0]->num; p[1] = poly[j][1]->num; p[2] = poly[j][2]->num; p[3] = poly[j][3]->num; Mis.InsertionSort(3,p); while (NOT saiu) { for (l = 0; l < top->cell.ne; l++) { ??? q = top->cell[l]; ??? q1 = q.node[0]->num; ??? q2 = q.node[1]->num; ??? q3 = q.node[2]->num; ??? q4 = q.node[3]->num; { if ((p[0]==q1) && (p[1]==q2) && (p[2]==q3) && ((p[3]==q4) )){ saiu = TRUE; } } } } } } } } /* END TestePolyExist */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) v: REF ARRAY OF INTEGER; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { for (i = 0; i < top->node.ne; i++) { ??? a = top->node[i]; ??? poly = Triangulation.StarOfNode(a; with (top), double dg = Triangulation.DegreeOfNode(a); double np = Triangulation->numberPolyOfStar(poly); double nvs = dg; double nfs = np; double nes = @{Edge->?}sOnThe@{Link->?}(a,poly,np) ){ /* ===> (2) condition : For All "v", degree(v) <= NV.top */ assert(dg <= top->node.ne); /* ===> (3) condition : Test the property (ii) of combinatorics description of 3-manifolds without boundary, i.e: All 0-simplex in the triangulation K is a internal node: One internal node is every 0-simplex that have one @{link->?} homeomorphic to sphere S^{2}, so must to perform the euler's formula: nv-ne+nf == 2. */ if ((top->bdr == 0) && (top->node.ne-top->NE+top->wall.ne-top->cell.ne == 0)) { assert(nvs-nes+nfs == 2); } /* ===> (4) condition : Test the property (i) of combinatorics description of 3-manifolds without boundary, i.e: All 2-simplex in the triangulation K is a internal wall: One internal wall is every 2-simplex that incident in exactly two 3-simplex. */ if (top->bdr == 0) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; ??? p1 = PposP(a); Cell_t p2 = PnegP(a); { assert(p1!=p2); } } } if (o->listStar) { ??? star = Triangulation.Neighbors(a; with (top), double nv = Triangulation->numberNeighborNode(star) ){ assert(nv == dg); fprintf(stderr, "Org->num: " & Fmt.Int(Org(a)->num) & " "); fprintf(stderr, " Degree : " & Fmt.Int(dg) & "\n"); fprintf(stderr, "Nodes belong to star of node: " \ Fmt.Int(OrgV(a)->num) & ":\n"); v = NEW(REF ARRAY OF INTEGER, nv); for (k = 0; k < nv; k++) { v[k] = star[k]->num; } /*Mis.InsertionSort(nv-1,v);*/ for (k = 0; k < nv; k++) { fprintf(stderr, Fmt.Int(v[k]) & " "); } fprintf(stderr, "\n"); } fprintf(stderr, "\n"); } } } fprintf(stderr, "Condition 2 OK\n"); if (top->bdr == 0) { fprintf(stderr, "Condition 3 OK\n"); fprintf(stderr, "Condition 4 OK\n"); } return 0; } PROCEDURE @{Edge->?}sOnThe@{Link->?}( Place_t @p; *poly: REF ARRAY OF FourNodes_t; uint *np; ) : uint == CONST INIT_STACK_SIZE == 10000; VAR uint c; tri : REF ARRAY OF Tri; bi : REF ARRAY OF Bi; stack = NEW(REF ARRAY OF EndPoint, INIT_STACK_SIZE); nstack : uint = 0; bool_t Present(c: EndPoint) /* retorna verdadeiro se "c" esta na pilha, FALSE c.c */ uint nstack1 = nstack; VAR { while (nstack1 > 0) { nstack1 = nstack1 - 1; if (stack.e[nstack1] == c){ return TRUE; } } return FALSE; } Present; { tri = NEW(REF ARRAY OF Tri, np); bi = NEW(REF ARRAY OF Bi, np); /* As arestas da cinta do vertice */ for(i = 0; i < poly.ne; i++) { c = 0; for (j = 0; j < 4; j++) { if (( poly[i][j]->num!=OrgV(a)->num )){ tri[i,c] = poly[i][j]->num; c++; } } /* As arestas para cada wall, ordenadas */ for (l = 0; l < 3; l++) { if (( tri[i,l] < tri[i,(l+1) % 3] )){ bi[i,l,0] = tri[i,l]; bi[i,l,1] = tri[i,(l+1) % 3]; } else { bi[i,l,0] = tri[i,(l+1) % 3]; bi[i,l,1] = tri[i,l]; } } } /* Achando o numero de arestas sob a superficie da vizinhanca */ for(j = 0; j < poly.ne; j++) { for (l = 0; l < 3; l++) { if ((! Present(bi[j,l]) )){ stack.e[nstack] = bi[j,l]; nstack++; } } } return nstack; } /* END @{Edge->?}sOnThe@{Link->?} */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); o->listStar = argparser_keyword_present(pp, "-listStar"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestTopology" \ " -inFile " \ " [ -listStar ]\n" \ "\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestTopology. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/OctfExtensions.h #ifndef OctfExtensions_H #define OctfExtensions_H // #TIMESTAMP /* Last edited on 2007-01-27 17:57:06 by stolfi */ /* Extensions to the facet-edge data strcuture. */ #define OctfExtensions_H_copyright \ "Copyright © 1998 Universidade Estadual de Campinas (UNICAMP)" /* ELEMENT ORIENTATIONS The /canonical {d}-dimensional simplex/ {K^d} is the regular tetrahedron in {R^{d+1}} whose vertices are the unit points on each axis, {u[d,0] = (1,0,...,0), u[d,1] = (0,1,...,0), ..., u[d,d] = (0,0,...,1)}. Let $p$ be a place in either map, and $h$ be any homeomorphism from {K^3} to {p.s$} that takes the corner {u[3,i]} of {K^3} to knot {p.knt[i]} of {p.s}, for all {i} in {0..3}. The /orientation defined by {p} on {p.s$}/ is the class of homeomorphisms of {K^3} to {p.s$} that is smoothly deformable to {h}. The orientation defined by {s} on {s$} induces internal orientations for the elements of {s} . An orientation of a node is just a sign {+} or {-}. An internal orientation on an edge allows us to distinguish {+} from {-} continuous travel along it. An internal orientation of a wall {f} allows us to distinguish {+} and {-} traversal of any Jordan curve on {f}. So, for instance, the {+} travel along {e.elm[1]} is the one that traverses the link {r} of {s} with {M}-type {{0,1}} in the direction from {(s,M).knt[0]} to {(s,M).knt[1]}. Observe that the knots {(s,M).knt[i]} and {(s,M).knt[1]} are always distinct, whereas the two endpoints of {e} may be the same node of {M}. Similarly, the {+} orientation on {s.elm[2]} is that which agrees with the oriented triangle {s.knt[0],s.knt[1],s.knt[2]}. even then, {s} and {t} will imply different orientations for at least one element of that element sequence. In particular, each chip {s} defines The orientation provided by {s} on its elements makes it possible to move around {M} without ambiguity, e.g. by defining what is the `origin' of the edge {e = (s,M).elm[1]}; the `next edge' after {e} around wall [f = (s,M).elm[2]}; and so forth. */ */ /* ORIENTED DATA POINTERS The value of each slot {p.data[i]} is an /oriented data pointer/, which consists of a /base data pointer/ combined with /data orientation bits/. These bits depend on the internal and external orientation of the element {p.e[i]}, and which of the two maps {p} belongs to. The operations {iflip}, {oflip} and {dual} apply to oriented data pointers. They preserve the data pointer and change the orientation bits: {iflip} and {oflip} reverse the internal and external orientations, respectively, and {dual} exchanges the underlying map. The three operators satisfy the identities {iflip.oflip == oflip.iflip}, {iflip.dual == dual.oflip}, {oflip.dual == dual.iflip}, {oflip.oflip == iflip.iflip == dual.dual == nop}. Moreover, for any oriented data pointer {t}, all eight oriented pointers {t.oflip^o.iflip^i.dual^d} are distinct. The data structure enforces the identities {p.flp[0].data[1] == p.data[1].iflip} {p.flp[0].data[2] == p.data[2].iflip} {p.flp[3].data[1] == p.data[1].oflip} {p.flp[3].data[2] == p.data[2].oflip} {p.dual.data[i] == p.data[3-i].dual} */ #define OctfExtensions_H_author \ "Created by J. Stolfi, UNICAMP in jan/2007." // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/TriangulationRest.c /* See {Triangulation.h}. */ // #INCLUDE // #TIMESTAMP /* Last edited on 2007-01-25 10:04:42 by stolfi */ /* Rest of implementation of {Triangulation.c} [JS 2007-01-24-222100 ] */ /* GLOBAL PROCEDURES */ #define INIT_STACK_SIZE 1024 Place_vec_t RenumberWedges(Place_vec_t *pv) { Place_vec_t pstack = Place_vec_new(INIT_STACK_SIZE); uint nstack = 0; uint seen = 0; /* Number of wedges whose childeren were looked at */ /* A wedge {n} is "marked" if PWedge(pstack.e[n.num]) == n. i.e whether stacked */ auto void VisitAndMark(Place_t t); /* If {t} is unmarked: visit, mark, and stack it. */ void VisitAndMark(Place_t t) { Wedge_t w = PWedge(t); if ((w->num < nstack) && (PWedge(pstack.e[w->num]) == w)) { /* wedge is already marked, do nothing. */ } else { Place_vec_expand(&pstack,nstack); w->num = nstack; pstack.e[nstack] = t; nstack++; } } /* Enumerate wedges: */ int i; for (i = 0; i < pv->ne; i++) { VisitAndMark(pv->e[i]); } while (seen < nstack) { Place_t s = pstack.e[seen]; VisitAndMark(PrevF(s)); VisitAndMark(PrevE(s)); VisitAndMark(NextE(s)); VisitAndMark(NextF(PrevE(s))); seen++; } /* Trim and return the {pstack}: */ Place_vec_trim(&pstack,nstack); return pstack; } static Node_vec_t seenNode = Node_vec_new(INIT_STACK_SIZE); /* A stack of {Node_t}s used by {NumberNodes} below. */ static uint seenNodeCount = 0; /* During {NumberNodes}, {seenNode[0..seenNodeCount-1]} are the node records renumbered so far. */ static uint_vec_t nodeOnum = uint_vec_new(INIT_STACK_SIZE); /* During {NumberNodes}, {nodeOnum[i]} is the saved node number of {seenNode[i]}, for {i} in {0..seenNodeCount-1}. */ void MarkNode(Node_t n) { /* Stack the node {n}: */ Node_vec_expand(&seenNode, seenNodeCount); seenNode.e[seenNodeCount] = n; /* Save its old number, and renumber it with position in {seenNode}: */ uint_vec_expand(&nodeOnum, seenNodeCount); nodeOnum.e[seenNodeCount] = n->num; n->num = seenNodeCount; /* Now we have one more node in {seenNode}: */ seenNodeCount++; } bool_t NodeIsMarked(Node_t n) { return ((n->num < seenNodeCount) && (seenNode.e[n->num] == n)); } void UnmarkMarkedNodes(void) { while (seenNodeCount > 0) { int k = seenNodeCount - 1; Node_t n = seenNode.e[k]; n->num = nodeOnum.e[k]; seenNodeCount--; } } void EnumNodes(Place_t p, visit: VisitFunc_t) { Place_vec_t pstack = Place_vec_new(INIT_STACK_SIZE); uint top; /* top for {pstack} */ void Stack(Place_t c) { Place_t cn = c; do { Place_vec_expand(&pstack, top); pstack.e[top] = cn; top++; Place_t dn = Clock(PrevE(cn)); do { Place_vec_expand(&pstack, top); pstack.e[top] = dn; top++; dn = NextF(dn); } while (!(( dn == Clock(PrevE(cn))))); cn = NextF(cn); } while (cn != c); } Stack; void VisitAndMark(Place_t c) /* If org(c) is diferent that the origins @places stacked, stack the @place {c}. */ Place_t *cn; { ??? n = Org(c); { if ((n!=NULL) && (NOT NodeIsMarked(n))) { visit(c); MarkNode(n); Stack(c); cn = c; do { Stack(cn); cn = ONext(cn); } while (!( (cn == c))); } } } VisitAndMark; uint *seen; { top = 0; seen = 0; assert(seenNodeCount == 0); VisitAndMark(a); while (seen < top) { Place_t b = (Place_t){festack.e[seen], bstack.e[seen]}; { VisitAndMark(NextF(b)); VisitAndMark(NextF(NextE(b))); VisitAndMark(NextE(b)); VisitAndMark(PrevF(PrevE(b))); } seen++; } UnmarkMarkedNodes(); } /* END EnumNodes */ uint NumberNodes(Place_t @p) uint n = 0; void Visit(Place_t c) void Visit_(Place_t c) Place_t *cn,dn; { ??? v = Org(c); { cn = c; do { ??? vn = Org(cn); { assert(vn == v); vn->num = n; dn = Clock(PrevE(cn)); do { ??? wn = Org(dn); { assert(wn == vn); wn->num = n; dn = NextF(dn); } } while (!(( dn == Clock(PrevE(cn))))); cn = NextF(cn); } } while (!( cn == c)); } } Visit_; Place_t cn = c; VAR { do { Visit_(cn); cn = ONext(cn); } while (cn != c); n++; } Visit; void VisitDual(Place_t c) void VisitDual_(Place_t c) VAR Place_t cn; p,pn: Node_t; { p = Org(c); if (p != NULL) { cn = c; do { pn = Org(cn); if (pn != NULL) { assert(pn == p); pn->num = n; } cn = NextF(cn); } while (!( cn == c)); } } VisitDual_; Place_t cn = c; VAR { VisitDual_(cn); VisitDual_(Clock(PrevE(cn))); n++; } VisitDual; { if ((Octf.DualBit(a) == 0)) { EnumNodes(a, Visit); } else { EnumNodes(a, VisitDual); } return n; } /* END NumberNodes */ TetraCorners GetTetraCorners(Place_t @p) TetraCorners *c; { ??? a0 = a; Place_t a1 = NextE(a0); Place_t a2 = NextE(a1); Place_t b0 = Clock(PrevF(a0)); Place_t c0 = Clock(PrevF(a1)); Place_t d0 = Clock(PrevF(a2)); { /* the 12 elements on the array must have the same negative cell. */ c[0 ] = a0; c[1 ] = NextE(a0); c[2 ] = PrevE(a0); c[3 ] = b0; c[4 ] = NextE(b0); c[5 ] = PrevE(b0); c[6 ] = c0; c[7 ] = NextE(c0); c[8 ] = PrevE(c0); c[9 ] = d0; c[10] = NextE(d0); c[11] = PrevE(d0); assert(c[0] == a); } return c; } /* END GetTetraCorners */ Place_vec_t *CollectTetrahedra(ElemTableRec_t *top)== seen,processed,conflicts: uint = 0; { ??? rt = Place_vec_new(top.cell.ne); ??? t = rt^; ??? q = Place_vec_new(top.cell.ne); { for (i = 0 TO (t.ne-1)) { t[i] = PlaceInWedge(NULL, 0); } for (k = 0 TO (t.ne-1)) { if ((PWedge(t[k]) == NULL)) { t[k] = Tors(Srot(top.cell[k])); q[seen] = t[k]; seen++; while (processed < seen) { ??? a = q[processed]; { void Visit(f: Place_t) { if ((Pneg(f) == NULL)){ return; } assert(Consistent(a,f)); ??? n = Pneg(f)->num; { if ((PWedge(t[n]) == NULL)) { t[n] = f; q[seen] = f; seen++; } else { assert(Pneg(t[n])->num == n); if ((! SameOrientation(t[n],f))){ conflicts++;} } } } Visit; bool_t Consistent(p,q:Place_t) /* Checks whether Pneg(q) and the Pneg(q) are adjacentes tetrahedra with consistent orientations. */ { ??? cp = GetTetraCorners(p); ??? cq = GetTetraCorners(q); { for (i = 0; i < 12; i++) { for (j = 0; j < 12; j++) { if ((cp[i] == Clock(cq[j]))){ return TRUE; } } } return FALSE; } } Consistent; bool_t SameOrientation(p,q:Place_t) /* Checks whether Pneg(p) == Pneg(q) and both have the same orientation. */ { ??? cp = GetTetraCorners(p); { for (i = 0; i < 12; i++) { if (cp[i] == q){ return TRUE; } } return FALSE; } } SameOrientation; { Place_t b = NextF(a); Place_t c = PrevF(NextE(a)); Place_t d = PrevF(PrevE(a)); ??? e == PrevF(a); { Visit(b); Visit(c); Visit(d); Visit(e); } } processed++; } } } } if (conflicts != 0) { fprintf(stderr, "CollectTetrahedra: conflicts == " & Fmt.Int(conflicts) & "\n"); } assert(processed == top.cell.ne); return rt; } } /* END CollectTetrahedra */ uint DegreeOfNode(Place_t @p) { ??? @{edge->?} = Octf.RenumberEdgesOutOfNodes((Place_vec_t){a}); ??? degree = ((@{edge->?}^).ne); { return degree; } } /* END DegreeOfNode */ AdjacencyMatrix *MakeAdjacencyMatrix(ElemTableRec_t *top)== m = NEW(REF ARRAY OF ARRAY OF bool_t, top->node.ne, top->node.ne); { for (i = 0; i < top->node.ne; i++){ ??? mi = m[i]; { for (j = 0; j < top->node.ne; j++) { mi[j] = FALSE } } } for (ei = 0; ei < top->wall.nelE; ei++) { ??? a = top->wedge[ei]; { ??? i = Org(a)->num, j == Org(Clock(a))->num; { m[i,j] = TRUE; m[j,i] = TRUE; } } } return m; } /* END MakeAdjacencyMatrix */ bool_t TriviallyIsomorphic(ElemTableRec_t *ta, ElemTableRec_t *tb) { if ((ta.NV!=tb.NV ) || (ta.NF!=tb.NF ) || (ta.NE!=tb.NE ) || (ta.NP!=tb.NP ) || (ta.NFE!=tb.NFE )){ return FALSE; } int NFE = ta.NFE; { for (i = 0; i < NFE; i++) { VAR sPlace_t @p = PWedge(ta)->i]; sb: Place_t = PWedge(tb)->i]; { for (r = 0; r < 4; r++) { ??? na = Org(sa)->num; ??? nb = Org(sb)->num; { if (na != nb){ return FALSE;} } ??? za = GetPlaceNum_t(NextF(sa)); ??? zb = GetPlaceNum_t(NextF(sb)); { if (za != zb){ return FALSE;} } sa = Srot(sa); sb = Srot(sb); } } } } return TRUE; } /* END TriviallyIsomorphic */ void CheckOutAndRegion(ElemTableRec_t *top) { for (i = 0; i < top->node.ne; i++){ Node_t v = OrgV(top->node.e[i]); ??? e = top->node[i]; { assert(v->num == i); assert(Org(e) == v); } } for (i = 0; i < top->cell.ne; i++) { ??? p = top->cell[i]; ??? r = Srot(top.cell[i]); { assert(p->num == i); assert(Org(r) == p); } } } /* END CheckOutAndRegion */ PROCEDURE GetVariableNodes(ElemTableRec_t *top, VAR vr: ARRAY OF bool_t) { for (i = 0; i < top->node.ne; i++){ Node_t v = OrgV(top->node.e[i]); { vr[i] = NOT v.fixed; } } } /* END GetVariableNodes */ /* ===== GEOMETRIC TOOLS ===== */ void InitCoords( rand_t *coins; Coords_t *c; float radius = 1.0) { ??? r = ((double)radius); { for (i = 0 TO (c.ne-1)) { c[i] = (r4_t) { coins.longreal(-r, r), coins.longreal(-r, r), coins.longreal(-r, r), coins.longreal(-r, r) } } } } /* END InitCoords */ Coords_t *GenCoords(ElemTableRec_t *top) { ??? coins = NEW(Random.Default).init(TRUE); ??? r = r4_vec_new(top.node.ne); ??? c = r^; { for (i = 0 TO (c.ne-1)) { c[i] = (r4_t) { coins.longreal(-1.0, +1.0), coins.longreal(-1.0, +1.0), coins.longreal(-1.0, +1.0), coins.longreal(-1.0, +1.0) } } return r; } } /* END GenCoords */ r4_t Barycenter(ElemTableRec_t *top, Coords_t *c, bool_t all) b: r4_t = (r4_t){0.0, ..}; uint n = 0; { for (i = 0 TO (c.ne-1)){ Node_t v = OrgV(top->node.e[i]); { if ((all) || (v->exists)){ b = r4_Add(b, c[i]); N++; } } } if (N == 0) { return b; } else { return r4_Scale(1.0/n, b); } } /* END Barycenter */ r4_t PartialBarycenter(*v: Node_vec_t; *c: Coords_t; bool_t all) b: r4_t = (r4_t){0.0, ..}; uint n = 0; { for (k = 0 TO (c.ne-1)){ ??? vk = v[k], i == vk->num; { if ((all) || (vk->exists)){ b = r4_Add(b, c[i]); N++; } } } if (N == 0) { return b; } else { return r4_Scale(1.0/n, b); } } /* END PartialBarycenter */ double MeanNodeDistance(ElemTableRec_t *top, Coords_t *c, *ctr: r4_t; bool_t all; ) S: double = 0.0; uint n = 0; { for (i = 0 TO (c.ne-1)){ Node_t v = OrgV(top->node.e[i]); { if ((all) || (v->exists)) { ??? d2 = r4_DistSqr(ctr, c[i]); { S = S + d2 } N++ } } } if (N == 0) { return 1.0; } else { return sqrt(S/n); } } /* END MeanNodeDistance */ double MaxNodeDistance(ElemTableRec_t *top, Coords_t *c; *ctr: r4_t; bool_t all; ) radius = 0.0; { for (i = 0; i < top->node.ne; i++){ Node_t v = OrgV(top->node.e[i]); { if ((all) || (v->exists)) { ??? d = r4_Dist(ctr, c[i]); { if (d > radius){ radius = d;} } } } } return radius; } /* END MaxNodeDistance */ double MeanThickness(ElemTableRec_t *top, Coords_t *c, r4_t *ctr, r4_t *norm, bool_t all) S : double = 0.0; uint n = 0; { for (i = 0; i < top->node.ne; i++){ Node_t v = OrgV(top->node.e[i]); { if ((all) || (v->exists)) { ??? d = r4_dot(r4_Sub(c[i],ctr), norm); { S = S + d*d; } N++ } } } if (N == 0) { return 1.0; } else { return sqrt(S/n); } } /* END MeanThickness */ double MeanEdgeLength(ElemTableRec_t *top, Coords_t *c, bool_t all) S: double = 0.0; uint n = 0; { for (i = 0; i < top->NE; i++){ ??? e = top->edge[i]; { if ((all) || (e->exists)) { Node_t o = OrgV(e.pa)->num, d == OrgV(Clock(e.pa))->num; { S = S + r4_DistSqr(c[o], c[d]) } N++; } } } if (N == 0) { return 1.0; } else { return sqrt(S/n); } } /* END MeanEdgeLength */ r4_t MeanCellNormal(ElemTableRec_t *top, Coords_t *c, bool_t all) norm: r4_t = (r4_t){0.0, ..}; { for (i = 0; i < top->cell.ne; i++){ Place_t f = Tors(Srot(top.cell[i])), p == PnegP(f); { if ((all) || ((p!=NULL) && (p->exists))) { ??? n = PolyCross(f, c); { norm = r4_Add(norm, n) } } } } ??? m = r4_Norm(norm); { if (m < 1.0d-20) { return (r4_t){0.0, 0.0, 0.0, 1.0}; } else { return r4_Scale(1.0/m, norm); } } } /* END MeanCellNormal */ void Displace(ElemTableRec_t *top, r4_t *d, Coords_t *c) { for (i = 0 TO (c.ne-1)){ if (OrgV(top->node.e[i])->exists) { ??? vc = c[i]; { vc = r4_Add(vc, d);} } } } /* END Displace */ void Scale(ElemTableRec_t *top, double s, Coords_t *c) { for (i = 0 TO (c.ne-1)){ if (OrgV(top->node.e[i])->exists) { ??? vc = c[i]; { vc = r4_Scale(s, vc); } } } } /* END Scale */ void NormalizeNodeDistances(ElemTableRec_t *top, Coords_t *c; bool_t all) { ??? b = Barycenter(top, c, all); { Displace(top, r4_Neg(b), c) } double s = MeanNodeDistance(top, c, (r4_t){0.0, ..}, all); { Scale(top, 1.0/s, c) } } /* END NormalizeNodeDistances */ void NormalizeEdgeLengths(ElemTableRec_t *top, Coords_t *c; bool_t all) { ??? b = Barycenter(top, c, all); { Displace(top, r4_Neg(b), c) } ??? s = MeanEdgeLength(top, c, all); { Scale(top, 1.0/s, c) } } /* END NormalizeEdgeLengths */ r4_t WallCross(Place_t @p, Coords_t *c) { if ((! PWall(a)->exists)){ return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { Node_t ov = OrgV(a); Node_t dv = OrgV(Clock(a)); Node_t pv = OrgV(PrevE(a)); Node_t qv = OrgV(PrevE(NextF(a))); Node_t rv = OrgV(PrevE(PrevF(a))); { ??? o = c[ov->num]; ??? d = c[dv->num]; ??? p = c[pv->num]; ??? q = c[qv->num]; ??? r = c[rv->num]; ??? n1 = r4_cross(r4_Sub(p,o), r4_Sub(r,o), r4_Sub(d,o)); ??? n2 = r4_cross(r4_Sub(p,o), r4_Sub(d,o), r4_Sub(q,o)); { return r4_Add(n1,n2); } } } } WallCross; r4_t WallNormal(Place_t @p, Coords_t *c) { ??? n = WallCross(a,c); ??? s = r4_Norm(n); { if (s == 0.0) { return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { return r4_Scale(1.0/s, n); } } } /* END WallNormal */ r4_t PolyCross(Place_t @p, Coords_t *c) { if ((! PnegP(a)->exists)){ return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { Node_t ov = OrgV(a); Node_t dv = OrgV(Clock(a)); Node_t pv = OrgV(PrevE(a)); Node_t rv = OrgV(PrevE(PrevF(a))); { ??? o = c[ov->num]; ??? d = c[dv->num]; ??? p = c[pv->num]; ??? r = c[rv->num]; { return r4_cross(r4_Sub(p,o), r4_Sub(r,o), r4_Sub(d,o)); } } } } PolyCross; r4_t PolyNormal(Place_t @p, Coords_t *c) { ??? n = PolyCross(a, c); ??? s = r4_Norm(n); { if (s == 0.0) { return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { return r4_Scale(1.0/s, n); } } } /* END PolyNormal */ r4_t WallBarycenter(Place_t @p, Coords_t *c) VAR Place_t @po; n : uint = 0; sum = (r4_t){0.0, ..}; { ao = a; do { ??? aoc = c[OrgV(ao)->num]; { sum = r4_Add(sum, aoc); n++; ao = NextE(ao); } } while (ao != a); if (n == 0) { return sum; } else { return r4_Scale(1.0/FLOAT(n,double), sum); } } /* END WallBarycenter */ r4_t TetraBarycenter(Place_t @p, Coords_t *c) uint n = 0; sum = (r4_t){0.0, ..}; { ??? tetra = TetraNegNodes(a); { for (i = 0; i < 4; i++) { ??? aoc = c[tetra[i]->num]; { sum = r4_Add(sum, aoc); n++; } } } return r4_Scale(1.0/FLOAT(n,double), sum); } /* END TetraBarycenter */ r4_t EdgeCross(Place_t @p, Coords_t *c) sum: r4_t = (r4_t){0.0,..}; Place_t @po; { Node_t uv = OrgV(a); ??? u = c[uv->num]; { if ((! PEdge(a)->exists)) { return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { ao = a; do { Place_t an = PrevF(ao); Node_t dv = OrgV(Clock(ao)); Node_t pv = OrgV(PrevE(ao)); Node_t rv = OrgV(PrevE(an)); { ??? d = c[dv->num]; ??? p = c[pv->num]; ??? r = c[rv->num]; ??? n = r4_cross(r4_Sub(p,u), r4_Sub(d,u), r4_Sub(r,u)); { if (ao == a){ sum = n; }else{ sum = r4_Add(sum,n); } } ao = an; } } while (ao != a); return sum; } } } /* END EdgeCross */ r4_t EdgeNormal(Place_t @p, Coords_t *c) { ??? n = EdgeCross(a, c); ??? s = r4_Norm(n); { if (s == 0.0) { return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { return r4_Scale(1.0/s, n); } } } /* END EdgeNormal */ r4_t NodeCross(Place_t @p, Coords_t *c, ElemDataRec_t *top) sum,n: r4_t = (r4_t){0.0, ..}; { Node_t uv = OrgV(a); ??? poly = StarOfNode(a,top); { if (! uv->exists) { return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { for(i = 0; i < poly.ne; i++) { if ((poly[i][0]->exists) && (poly[i][1]->exists AND poly[i][2]->exists) && (poly[i][3]->exists )){ ??? u = c[poly[i][0]->num]; ??? d = c[poly[i][1]->num]; ??? p = c[poly[i][2]->num]; ??? r = c[poly[i][3]->num]; { n= r4_cross(r4_Sub(p,u), r4_Sub(d,u), r4_Sub(r,u)); if (i == 0){ sum = n; }else{ sum = r4_Add(sum,n); } } } } } return sum; } } /* END NodeCross */ r4_t NodeNormal(Place_t @p, Coords_t *c, ElemTableRec_t *top) { ??? n = NodeCross(a, c, top); ??? s = r4_Norm(n); { if (s == 0.0) { return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { return r4_Scale(1.0/s, n); } } } /* END NodeNormal */ Node_vec_t *Neighbors( Node v; *ElemTableRec_t *top; )== REF Node_vec_t rv = NULL; nv: uint = 0; void Stack(u: Node) { if ((rv == NULL) || (nv >= ((rv^).ne))) { ??? sv = NEW(REF Node_vec_t, MAX(10, 2*nv)); { if (rv != NULL){ SUBARRAY(sv^, 0, nv) = rv^; } rv = sv } } rv[nv] = u; nv++; } Stack; void Check(b: Place_t) { if ((OrgV(b) == v)){ Stack(OrgV(Clock(b)));} } Check; { for (i = 0; i <= (top->NE - 1); i++){ ??? ei = top->edge[i].pa; { Check(ei); Check(Clock(ei)) } } Node_vec_trim(&rv,nv); } /* END Neighbors */ Quadv_vec_t *StarOfNode(Place_t @p, ElemTableRec_t *top)== PROCEDURE NodePoly(ElemDataRec_t *top): REF ARRAY OF Quadp == /* Return four places such as the origins corresponding to nodes extremes of each tetrahedron of Triangulation. */ REF ARRAY OF Quadp poly = NEW(REF ARRAY OF Quadp, top->cell.ne); { for (i = 0; i < top->cell.ne; i++) { ??? da = Srot(top.cell[i]); Place_t a0 = Tors(da); Place_t db = Clock(PrevE(da)); Place_t b0 = Tors(db); { /*assert(DegreeOfNode(a0) == 4); */ /* consuming time */ Place_t a1 = NextE(a0); Place_t a2 = NextE(a1); Place_t a3 = PrevE(b0); { if ((NextE(a2)!=a0)) { fprintf(stderr, "\nTriangulation: This topology isn't" \ " a triangulation\n"); assert(NextE(a2) == a0); } assert(Pneg(a0)->num == i); if ((Pneg(b0)!=NULL)) { assert(Pneg(a0) == Pneg(b0)); } assert(a0!=b0); poly[i] = Quadp{a0,a1,a2,a3}; } } } return poly; } NodePoly; poly1 : REF Quadv_vec_t = Quadv_vec_new(top->cell.ne); n : uint = 0; { ??? poly = NodePoly(top), v == OrgV(a); { for(i = 0; i < poly.ne; i++) { if (((OrgV(poly[i][0]) == v)) || ((OrgV(poly[i][1]) == v) OR (OrgV(poly[i][2]) == v)) || ((OrgV(poly[i][3]) == v) )){ for (j = 0; j < 4; j++) { if ((OrgV(poly[i][j]) == v )){ Node_t uv = OrgV(poly[i][j]); Node_t dv = OrgV(NextE(poly[i][j])); Node_t pv = OrgV(PrevE(poly[i][j])); Node_t rv = OrgV(PrevE(PrevF(poly[i][j]))); { poly1[n] = Quadv{uv,dv,pv,rv}; n++; } } } } } Quadv_vec_trim(&poly1,n); } } /* END StarOfNode */ uint NumberPolyOfStar(Quadv_vec_t *qv) { ??? n = (qv->ne); { return n; }; } /* END NumberPolyOfStar */ r4_vec_t *ComputeAllNodeNormals( *ElemTableRec_t *top; Coords_t *c; )== { ??? rvn = r4_vec_new(top->node.ne); ??? vn = rvn^; { for (i = 0; i < top->node.ne; i++) { vn[i] = NodeNormal(top->node[i], c, top) } return rvn } } /* END ComputeAllNodeNormals */ r4_vec_t *ComputeAllEdgeNormals(ElemTableRec_t *top, Coords_t *c; )== { ??? rvn = r4_vec_new(top->NE); ??? vn = rvn^; { for (i = 0; i < top->NE; i++) { vn[i] = EdgeNormal(top->edge[i].pa, c); } return rvn } } /* END ComputeAllEdgeNormals */ r4_vec_t *ComputeAllWallNormals(ElemTableRec_t *top, Coords_t *c; )== { ??? rvn = r4_vec_new(top->wall.ne); ??? vn = rvn^; { for (i = 0; i < top->wall.ne; i++) { vn[i] = WallNormal(top->wall[i].pa, c); } return rvn } } /* END ComputeAllWallNormals */ r4_vec_t *ComputeAllCellNormals(ElemTableRec_t *top, Coords_t *c; )== { ??? rvn = r4_vec_new(top->cell.ne); ??? vn = rvn^; { for (i = 0; i < top->cell.ne; i++) { vn[i] = PolyNormal(Tors(Srot(top.cell[i])), c); } return rvn } } /* END ComputeAllCellNormals */ CellTopology MakeCellTopology(Place_t @p) VAR uint ne, nv; Place_t b, bn; ptop: CellTopology; { ??? pneg = Org(a); ??? star = Octf.RenumberEdgesOutOfNodes((Place_vec_t){a})^; { /* Gather walls: */ ptop.wall.ne = (star.ne); ptop.fRef = Place_vec_new(ptop.wall.ne); ne = 0; for (i = 0; i < ptop.wall.ne; i++) { ??? side = Octf.Dual(star[i]); { ptop.fRef[i] = side; assert(Pneg(ptop.fRef[i]) == pneg); b = side; do { ne++; Edge_t e = PEdge(b); { e.xmark = FALSE; OrgV(b).xmark = FALSE; /* OrgV(b).xmark = FALSE */ } b = NextE(b) } while (b != side); } } /* Gather @{edge->?}s: */ assert(ne % 2 == 0); ptop.edge.ne = ne DIV 2; ptop.eRef = Place_vec_new(ptop.edge.ne); ne = 0; for (i = 0; i < ptop.wall.ne; i++) { ??? side = Octf.Dual(star[i]); { b = side; do { Edge_t e = PEdge(b); { if (! e.xmark) { ptop.eRef[ne] = b; assert(Pneg(ptop.eRef[ne]) == pneg); bn = b; do { PEdge(bn).xmark = TRUE; bn = NextF(bn); } while (bn != b); ne++; } } b = NextE(b) } while (!( b == side)); } } /* Gather nodes: */ ptop.node.ne = 2 + ptop.edge.ne - ptop.wall.ne; ptop.vRef = Place_vec_new(ptop.node.ne); nv = 0; for (i = 0; i < ptop.edge.ne; i++) { ??? eu = ptop.eRef[i]; Node_t u = OrgV(eu); Place_t ev = Clock(PrevF(eu)); Node_t v = OrgV(ev); { if (! u.xmark) { ptop.vRef[nv] = eu; assert(Pneg(ptop.vRef[nv]) == pneg); nv++; u.xmark = TRUE; } if (! v.xmark){ ptop.vRef[nv] = ev; assert(Pneg(ptop.vRef[nv]) == pneg); nv++; v.xmark = TRUE; } PEdge(eu).xmark = FALSE; } } for (i = 0; i < ptop.node.ne; i++){ Node_t u = OrgV(ptop.vRef[i]); { u.xmark = FALSE; } } } return ptop; } /* END MakeCellTopology */ /* =============== INPUT/OUTPUT =========================== */ CONST BoolChars == Mis.BoolChars; AlphaChars == Mis.AlphaChars; TopCom_t ReadTopology(FILE *rd) VAR ElemTableRec_t *top; char *cmt; CHAR n; { /* Topology */ ReadHeader(rd,"topology","99-08-25"); cmt = filefmt_read_comment(rd, '|'); /* Element counts: */ Lex.Skip(rd, cs = AlphaChars); top->node.ne = fget_int32(rd); Lex.Skip(rd, cs = AlphaChars); top->NE = fget_int32(rd); Lex.Skip(rd, cs = AlphaChars); top->wall.ne = fget_int32(rd); Lex.Skip(rd, cs = AlphaChars); top->cell.ne = fget_int32(rd); Lex.Skip(rd, cs = AlphaChars); top->wall.nelE = fget_int32(rd); Lex.Skip(rd, cs = AlphaChars); EVAL fget_int32(rd); /* top->der */ Lex.Skip(rd, cs = AlphaChars); EVAL fget_int32(rd); /* top->bdr */ Lex.Skip(rd); ??? map = NEW(REF ARRAY OF Octf.wedge, top->wall.nelE)^; { /* Create node records: */ top->node = Node_vec_new(top->node.ne); top->node = Place_vec_new(top->node.ne); for (i = 0; i < top->node.ne; i++){ top->node[i] = MakeNode(); } /* Create @{edge->?}s records */ top->edge = NEW(REF ARRAY OF Octf.edge, top->NE); for (i = 0; i < top->NE; i++) { top->edge[i] = Octf.Make@{Edge->?}(); for (j = 0; j < 2; j++) { top->edge[i].node[j] = MakeNode(); } } /* Create wall records: */ top->wall = Wall_vec_new(top->wall.ne); for (i = 0; i < top->wall.ne; i++) { top->wall[i] = Octf.MakeWall(); /* top->wall[i].node = NEW(REF ARRAY OF Node_t,top->der); for (j = 0; j < top->der; j++) { top->wall[i].node^[j] = MakeNode(); } */ } /* Create cells records: */ top->cell = Place_vec_new(???); for (i = 0; i < top->cell.ne; i++) { top->cell[i] = MakeCell(); /* if ( top->der == 3) { if (top->bdr == 2) { /* Obs: bdr==2 indicate that the cells are octahedra. */ top->cell[i].node = NEW(REF ARRAY OF Node_t,top->der+3); for (j = 0; j <= (top->der+2); j++) { top->cell[i].node^[j] = MakeNode(); } } else { top->cell[i].node = NEW(REF ARRAY OF Node_t,top->der+1); for (j = 0; j <= (top->der); j++) { top->cell[i].node^[j] = MakeNode(); } } } else if (top->der == 4){ top->cell[i].node = NEW(REF ARRAY OF Node_t,2*top->der); for (j = 0; j <= (2*top->der-1); j++) { top->cell[i].node^[j] = MakeNode(); } } else if (top->der == 2){ top->cell[i].node = NEW(REF ARRAY OF Node_t,2); for (j = 0; j < 2; j++) { top->cell[i].node^[j] = MakeNode(); } } else if (top->der == 5){ top->cell[i].node = NEW(REF ARRAY OF Node_t,4*top->der); for (j = 0; j < 20; j++) { top->cell[i].node^[j] = MakeNode(); } } */ } /* Create wedge records: */ top->wedge = NEW(REF ARRAY OF Octf_Place_t, top->wall.nelE); for (i = 0; i < top->wall.nelE; i++) { top->wedge[i] = MakeWedge(); PWedge(top->wedge[i])->num = i; map[i] = PWedge(top->wedge[i]); } /* Read @{edge->?} data: */ EVAL filefmt_read_comment(rd, '|'); for (j = 0; j < top->NE; j++) { Lex.Skip(rd); ??? ne = fget_int32(rd); /* index to @{edge->?} */ ??? e = top->edge[ne]; { assert(ne == j); e->num = ne; e->pa = Octf.ReadPlace(rd,map); } } Lex.Skip(rd); /* Read wall data: */ EVAL filefmt_read_comment(rd, '|'); for (j = 0; j < top->wall.ne; j++) { Lex.Skip(rd); ??? nf = fget_int32(rd); /* index to wall */ ??? f = top->wall[nf]; { assert(nf == j); f->num = nf; f->pa = Octf.ReadPlace(rd,map); } } Lex.Skip(rd); /* Read wedge data: */ EVAL filefmt_read_comment(rd, '|'); for (j = 0; j < top->wall.nelE; j++) { Lex.Skip(rd); ??? nfe = fget_int32(rd); /* index to wedge */ ??? fe = NARROW(PWedge(top->wedge[nfe]), Wedge_t); { assert(nfe == j); assert(top->wedge[nfe].bits == 0); fe->num = nfe; Octf.ReadWedge(rd, fe, map); for (k = 0; k < 4; k++) { Lex.Skip(rd); n = fgetc(rd); if (n!='-') { Rd.UnGetChar(rd); ??? m = fget_int32(rd); ??? vf = fe.org[k]; { if ((fgetc(rd) == 'v')) { vf = top->node[m]; top->node[m] = PlaceInWedge(fe, 2*k); } else { vf = top->cell[m]; top->cell[m] = Tors(PlaceInWedge(fe, 2*k)); } } } } Lex.Skip(rd); fe.wall->num = fget_int32(rd); assert(fgetc(rd) == 'f'); Lex.Skip(rd); fe->edge->num = fget_int32(rd); assert(fgetc(rd) == 'e'); } } ReadFooter(rd,"topology"); return (TopCom_t){top, cmt}; } } /* END ReadTopology */ void ReadMaterials( FILE *rd; *ElemTableRec_t *top; bool_t ro_te = FALSE; ) { /* Materials */ ReadHeader(rd,"materials","99-08-25"); /* Read node data Materials: */ EVAL filefmt_read_comment(rd, '|'); for (j = 0; j < top->node.ne; j++) { Lex.Skip(rd); int nv = fget_int32(rd); /* index to node */ ??? v = top->node[nv]; { assert(nv == j); v->num = nv; Lex.Skip(rd); v->exists = Mis.ReadBool(rd); Lex.Skip(rd); v.fixed = Mis.ReadBool(rd); Lex.Skip(rd); ??? cc = v.color; { cc.e[0] = Lex.Real(rd); Lex.Skip(rd); cc.e[1] = Lex.Real(rd); Lex.Skip(rd); cc.e[2] = Lex.Real(rd); } Lex.Skip(rd); ??? tt = v.transp; { tt[0] = Lex.Real(rd); Lex.Skip(rd); tt[1] = Lex.Real(rd); Lex.Skip(rd); tt[2] = Lex.Real(rd); } Lex.Skip(rd); v.radius = Lex.Real(rd); Lex.Skip(rd); v.label = Rd.GetText(rd,2); } } Lex.Skip(rd); /* Read @{edge->?} data materials: */ EVAL filefmt_read_comment(rd, '|'); for (j = 0; j < top->NE; j++) { Lex.Skip(rd); ??? ne = fget_int32(rd); /* index to @{edge->?} */ ??? e = top->edge[ne]; { assert(ne == j); e->num = ne; Lex.Skip(rd); e->exists = Mis.ReadBool(rd); Lex.Skip(rd); ??? cc = e.color; { cc.e[0] = Lex.Real(rd); Lex.Skip(rd); cc.e[1] = Lex.Real(rd); Lex.Skip(rd); cc.e[2] = Lex.Real(rd); } Lex.Skip(rd); ??? tt = e.transp; { tt[0] = Lex.Real(rd); Lex.Skip(rd); tt[1] = Lex.Real(rd); Lex.Skip(rd); tt[2] = Lex.Real(rd); } Lex.Skip(rd); e.radius = Lex.Real(rd); Lex.Skip(rd); e.degenerate = Mis.ReadBool(rd); Lex.Skip(rd); ??? n = fgetc(rd); { if (n!='-') { Rd.UnGetChar(rd); e->root = fget_int32(rd); } else { e->root = -1; } } } } Lex.Skip(rd); /* Read wall data materials: */ EVAL filefmt_read_comment(rd, '|'); for (j = 0; j < top->wall.ne; j++) { Lex.Skip(rd); ??? nf = fget_int32(rd); /* index to wall */ ??? f == top->wall[nf]; { assert(nf == j); f->num = nf; Lex.Skip(rd); f->exists = Mis.ReadBool(rd); Lex.Skip(rd); ??? cc = f.color; { cc.e[0] = Lex.Real(rd); Lex.Skip(rd); cc.e[1] = Lex.Real(rd); Lex.Skip(rd); cc.e[2] = Lex.Real(rd); } Lex.Skip(rd); ??? tt = f.transp; { tt[0] = Lex.Real(rd); Lex.Skip(rd); tt[1] = Lex.Real(rd); Lex.Skip(rd); tt[2] = Lex.Real(rd); } Lex.Skip(rd); f.degenerate = Mis.ReadBool(rd); Lex.Skip(rd); ??? n = fgetc(rd); { if (n!='-') { Rd.UnGetChar(rd); f->root = fget_int32(rd); } else { f->root = -1; } } } } Lex.Skip(rd); /* Read cell data materials: */ if (top->cell.ne!=0) { EVAL filefmt_read_comment(rd, '|'); } for (j = 0; j < top->cell.ne; j++) { Lex.Skip(rd); ??? np = fget_int32(rd); /* index to cell */ ??? p = top->cell[np]; { assert(np == j); p->num = np; Lex.Skip(rd); p->exists = Mis.ReadBool(rd); Lex.Skip(rd); ??? cc = p.color; { cc.e[0] = Lex.Real(rd); Lex.Skip(rd); cc.e[1] = Lex.Real(rd); Lex.Skip(rd); cc.e[2] = Lex.Real(rd); } Lex.Skip(rd); ??? tt = p.transp; { tt[0] = Lex.Real(rd); Lex.Skip(rd); tt[1] = Lex.Real(rd); Lex.Skip(rd); tt[2] = Lex.Real(rd); } Lex.Skip(rd); EVAL Mis.ReadBool(rd); /* p.degenerate */ if (ro_te) { Lex.Skip(rd); ??? n = fgetc(rd); { if (n!='-') { Rd.UnGetChar(rd); p->root = fget_int32(rd); } else { p->root = -1; } } } } } ReadFooter(rd,"materials"); fclose(rd); CheckOutAndRegion(top); } /* END ReadMaterials */ TopCom_t ReadToMa(char *name, bool_t ro_te /* DF FALSE */) /* Where ro_te meaning {root tetrahedron}. */ VAR TopCom_t tc; { ??? ntp = name & ".tp"; ??? rtp = FileRd.Open(ntp); { fprintf(stderr, "reading " & ntp & "\n"); tc = ReadTopology(rtp); fclose(rtp); } ??? nma = name & ".ma"; ??? rma = FileRd.Open(nma); { fprintf(stderr, "reading " & nma & "\n"); ReadMaterials(rma, tc.top, ro_te); fclose(rma); } return tc; } /* END ReadToMa */ Coords_t *ReadState(char *name)== <* FATAL Rd.Failure, Thread.Alerted,FloatMode.Trap, Lex.Error, OSError.E); Coords_t c; char *cmt; uint nv; { FILE *rd = open_read(fileName, TRUE); /* {name}.{st} */ { /* Read Headers File Formats*/ ReadHeader(rd,"state","99-08-25"); /* Element counts: */ Lex.Skip(rd, cs = AlphaChars); nv = fget_int32(rd); Lex.Skip(rd); cmt = filefmt_read_comment(rd, '|'); c = NEW(REF Coords_t, nv); /* Read node data state: */ for (j = 0; j < nv; j++) { Lex.Skip(rd); int nv = fget_int32(rd); { ??? cv = c[nv]; { cv[0] = fget_double(rd); Lex.Skip(rd); cv[1] = fget_double(rd); Lex.Skip(rd); cv[2] = fget_double(rd); Lex.Skip(rd); cv[3] = fget_double(rd); } } } ReadFooter(rd,"state"); fclose(rd); return c; } } /* END ReadState */ void WriteState(char *name, ElemTableRec_t *top, Coords_t *c, char *cmt /* DF "" */) <* FATAL OSError.E); { ??? st = FileWr.Open(name & ".st"); ??? vWidth = digits(top->node.ne - 1); { void WriteCoord(double x) { fprintf(st, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Sci, prec = 3), 7)); } WriteCoord; void WritePoint(*c: r4_t) { WriteCoord(c[0]); fprintf(st, " "); WriteCoord(c[1]); fprintf(st, " "); WriteCoord(c[2]); fprintf(st, " "); WriteCoord(c[3]); } WritePoint; { WriteHeader(st,"state","99-08-25"); fprintf(st, "nodes "); fprintf(st, Fmt.Int(top->node.ne) & "\n"); int ind = 0; /* Comment indentation. */ if (((cmt != NULL) && ((*cmt) != 0))) { filefmt_write_comment(st, cmt & "\n", ind, '|') } filefmt_write_comment(st, "\nNode data:\n", ind, '|'); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { /* state */ fprintf(st, Fmt.Pad(Fmt.Int(v->num), vWidth)); fprintf(st, " "); WritePoint(c[v->num]); fprintf(st, "\n"); } } } filefmt_write_footer(st, "state"); fclose(st); } } /* END WriteState */ void WriteMaterials(char *name, ElemTableRec_t *top, char *cmt /* DF "" */, bool_t ro_te = FALSE; /* root tetrahedron */ ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); INTEGER *pWidth; { if (top->cell.ne == 0){ pWidth = 2 }else{ pWidth = digits(top->cell.ne-1); } ??? ma = FileWr.Open(name & ".ma"); ??? vWidth = digits(top->node.ne-1); ??? fWidth = digits(top->wall.ne-1); ??? eWidth = digits(top->NE-1); { void WriteIntensity(r: REAL) { fprintf(ma, Fmt.Real(r, Fmt.Style.Fix, prec = 2)); } WriteIntensity; void WriteColor(*c: frgb_t) { WriteIntensity(c[0]); fprintf(ma, " "); WriteIntensity(c[1]); fprintf(ma, " "); WriteIntensity(c[2]); } WriteColor; void WriteRadius(r: REAL) { if (r == 0.02 ){ fprintf(ma, "0.020"); } else { fprintf(ma,Fmt.Real(r, prec = 4)); } } WriteRadius; void WriteLabel(char *label) { fprintf(ma, label); } WriteLabel; { WriteHeader(ma,"materials","99-08-25"); int ind = 0; /* Comment indentation. */ if (((cmt != NULL) && ((*cmt) != 0))) { filefmt_write_comments(ma, cmt & "\n", ind, '|') } ??? m = digits(top->cell.ne); { filefmt_write_comments(ma,"nodes " & Fmt.Pad(Fmt.Int(top->node.ne),m), ind, '|'); filefmt_write_comments(ma,"@{edge->?}s " & Fmt.Pad(Fmt.Int(top->NE),m), ind,'|'); filefmt_write_comments(ma,"walls " & Fmt.Pad(Fmt.Int(top->wall.ne),m), ind, '|'); filefmt_write_comments(ma,"cells " & Fmt.Int(top->cell.ne), ind, '|'); } filefmt_write_comments(ma, "\nNode data:\n", ind, '|'); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { /* materials */ fprintf(ma, Fmt.Pad(Fmt.Int(v->num), vWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[v->exists])); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[v.fixed])); fprintf(ma, " "); WriteColor(v.color); fprintf(ma, " "); WriteColor(v.transp); fprintf(ma, " "); WriteRadius(v.radius); fprintf(ma, " "); WriteLabel(v.label); fprintf(ma, "\n"); } } filefmt_write_comments(ma, "\n@{Edge->?} data:\n", ind, '|'); for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { /* materials */ fprintf(ma, Fmt.Pad(Fmt.Int(e->num), eWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[e->exists])); fprintf(ma, " "); WriteColor(e.color); fprintf(ma, " "); WriteColor(e.transp); fprintf(ma, " "); WriteRadius(e.radius); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[e.degenerate])); fprintf(ma, " "); if (e->root == -1) { fprintf(ma, " - "); } else { fprintf(ma, Fmt.Pad(Fmt.Int(e->root), eWidth)); } fprintf(ma, "\n"); } } filefmt_write_comments(ma, "\nWall data:\n", '|'); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { fprintf(ma, Fmt.Pad(Fmt.Int(f->num), fWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[f->exists])); fprintf(ma, " "); WriteColor(f.color); fprintf(ma, " "); WriteColor(f.transp); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[f.degenerate])); fprintf(ma, " "); if (f->root == -1) { fprintf(ma, " - "); } else { fprintf(ma, Fmt.Pad(Fmt.Int(f->root), fWidth)); } fprintf(ma, "\n"); } } if (top->cell.ne!=0) { filefmt_write_comments(ma, "\nCell data:\n", '|'); } for (i = 0; i < top->cell.ne; i++) { ??? p = top->cell[i]; { fprintf(ma, Fmt.Pad(Fmt.Int(p->num), pWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[p->exists])); fprintf(ma, " "); WriteColor(p.color); fprintf(ma, " "); WriteColor(p.transp); fprintf(ma, " "); ??? degenerate = FALSE; { fprintf(ma, Fmt.Char(BoolChars[degenerate])); } if (ro_te) { fprintf(ma, " "); if (p->root == -1) { fprintf(ma, " - "); } else { fprintf(ma, Fmt.Pad(Fmt.Int(p->root), pWidth)); } } fprintf(ma, "\n"); } } } filefmt_write_footer(ma, "materials"); fclose(ma); } } /* END WriteMaterials */ void Collectwedges(Place_t @p, Place_vec_t *re, uint *ne) Place_t *b; { b = a; ne = 0; do { assert(PWall(b) == PWall(a)); if ((re == NULL) || (ne >= ((re^).ne))) { ??? se = NEW(REF Place_vec_t, MAX(10, 2*ne)); { if (re != NULL){ SUBARRAY(se^, 0, ne) = re^; } re = se } } re[ne] = b; ne++; b = NextE(b) } while (b != a); } /* END Collectwedges */ void CollectCellWalls(Place_t @p, Place_vec_t *rf, uint *nf) scanned: uint = 0; void StackWall(Place_t c) { assert(Pneg(c) == Pneg(a)); PWall(c).xmark = TRUE; if ((rf == NULL) || (nf >= ((rf^).ne))) { ??? sf = NEW(REF Place_vec_t, MAX(10, 2*nf)); { if (rf != NULL){ SUBARRAY(sf^, 0, nf) = rf^; } rf = sf } } rf[nf] = c; nf++; } StackWall; void VisitWall(b: Place_t) Place_t c = Clock(PrevF(b)); VAR { do { assert(Pneg(c) == Pneg(a)); Wall_t g = PWall(c); { if (! g.xmark) { StackWall(c); /* We have only one mark per wall, but a wall may incide twice on "p": */ /* Assumes that the cell's boundary is oriented! */ if ((PposP(c) == Pneg(a))){ StackWall(Clock(c)); } } } c = NextE(c) } while (c != b); } VisitWall; { nf = 0; scanned = 0; StackWall(a); while (scanned < nf) { VisitWall(rf[scanned]); scanned++ } /* Clear {xmark}, just in case: */ for (k = 0; k <= (nf - 1); k++) { ??? b = rf[k]; { PWall(b).xmark = FALSE;} } } /* END CollectCellWalls */ void CollectCellEdges(Place_t @p, VAR Place_vec_t re; uint *ne; VAR Place_vec_t rf; /* Working area */ ) == uint *nf; Place_t b; { CollectCellWalls(a, rf, nf); ne = 0; for (k = 0; k < nf; k++) { ??? f = rf[k]; { assert(Pneg(f) == Pneg(a)); b = f; do { Edge_t e = PEdge(b); { if (! e.xmark) { if ((re == NULL) || (ne >= ((re^).ne))) { ??? se = NEW(REF Place_vec_t, MAX(10, 2*ne)); { if (re != NULL){ SUBARRAY(se^, 0, ne) = re^; } re = se } } e.xmark = TRUE; re[ne] = b; ne++ } } b = NextE(b) } while (b != f); } } /* Clear {xmark} bits: */ for (k = 0; k <= (ne - 1); k++) { ??? b = re[k]; { PEdge(b).xmark = FALSE;} } } /* END CollectCellEdges */ void CollectCellNodes(Place_t @p, Place_vec_t *rv, uint *nv, Place_vec_t *rf /* Working area */) uint *nf; Place_t b; { CollectCellWalls(a, rf, nf); nv = 0; for (k = 0; k <= (nf - 1); k++) { ??? f = rf[k]; { assert(Pneg(f) == Pneg(a)); b = f; do { Node_t v = OrgV(b); { if (! v.xmark) { if ((rv == NULL) || (nv >= ((rv^).ne))) { ??? sv = NEW(REF Place_vec_t, MAX(10, 2*nv)); { if (rv != NULL){ SUBARRAY(sv^, 0, nv) = rv^; } rv = sv } } v.xmark = TRUE; rv[nv] = b; nv++ } } b = NextE(b) } while (b != f); } } /* Clear {xmark} bits: */ for (k = 0; k < nv; k++) { ??? b = rv[k]; { OrgV(b).xmark = FALSE;} } } /* END CollectCellNodes */ void WriteTopology(char *name, ElemTableRec_t *top, char *cmt /* DF " " */) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); INTEGER *pWidth; { if (top->cell.ne == 0){ pWidth= 2 }else{ pWidth = digits(top->cell.ne-1); } ??? top = FileWr.Open(name & ".tp"); ??? vWidth = digits(top->node.ne - 1); ??? eWidth = digits(top->NE - 1); ??? fWidth = digits(top->wall.ne - 1); ??? feWidth = digits(top->wall.nelE -1); { WriteHeader(top,"topology","99-08-25"); if (((cmt != NULL) && ((*cmt) != 0))) { filefmt_write_comments(top, cmt & "\n", '|') } ??? m = digits(top->wall.nelE); { fprintf(top, "nodes "); fprintf(top, Fmt.Pad(Fmt.Int(top->node.ne),m) & "\n"); fprintf(top, "@{edge->?}s "); fprintf(top, Fmt.Pad(Fmt.Int(top->NE),m) & "\n"); fprintf(top, "walls "); fprintf(top, Fmt.Pad(Fmt.Int(top->wall.ne),m) & "\n"); fprintf(top, "cells "); fprintf(top, Fmt.Pad(Fmt.Int(top->cell.ne),m) & "\n"); fprintf(top, "wedges "); fprintf(top, Fmt.Int(top->wall.nelE) & "\n"); fprintf(top, "der "); ??? der = 0; { fprintf(top, Fmt.Pad(Fmt.Int(der),m) & "\n"); } fprintf(top, "bdr "); ??? bdr = 0; { fprintf(top, Fmt.Pad(Fmt.Int(bdr),m) & "\n"); } } filefmt_write_comments(top, "\n@{Edge->?} data:\n", '|'); for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { fprintf(top, Fmt.Pad(Fmt.Int(e->num), eWidth)); fprintf(top, " "); Octf.PrintPlace(top, e.pa, eWidth+1, TRUE); } } filefmt_write_comments(top, "\nWall data:\n", '|'); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { fprintf(top, Fmt.Pad(Fmt.Int(f->num), fWidth)); fprintf(top, " "); Octf.PrintPlace(top, f.pa, fWidth+1, TRUE); } } filefmt_write_comments(top, "\nwedge data:\n", '|'); for (i = 0; i < top->wall.nelE; i++) { ??? fe = NARROW(PWedge(top->wedge[i]), Wedge_t); { fprintf(top, Fmt.Pad(Fmt.Int(fe->num), feWidth)); fprintf(top, " "); Octf.PrintWedge(top, fe, feWidth); fprintf(top, " "); for (j = 0; j < 4; j++) { ??? n = fe.org[j]; { TYPECASE n OF break; case NULL: for (i = 0; i < (pWidth-1); i++){ fprintf(top," "); } fprintf(top, " - "); | Node(v) ==> fprintf(top, Fmt.Pad(Fmt.Int(v->num), vWidth) & "v "); | Cell(p) ==> fprintf(top, Fmt.Pad(Fmt.Int(p->num), pWidth) & "p "); } else { /* nothing */ } } } fprintf(top, " "); ??? f = fe.wall; { fprintf(top, Fmt.Pad(Fmt.Int(f->num), fWidth)); } fprintf(top, "f "); ??? e = fe->edge; { fprintf(top, Fmt.Pad(Fmt.Int(e->num), eWidth)); } fprintf(top, "e\n"); } } filefmt_write_footer(top, "topology"); fclose(top); } } /* END WriteTopology */ void WriteDualTopology(char *name, ElemTableRec_t *top, char *cmt /* DF " " */) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); void PrintDualPlace_t(FILE *wr, Place_t @p; feWidth: uint) { fprintf(wr,Fmt.Pad(Fmt.Int(PWedge(a)->num), feWidth) & ":" \ Fmt.Int((Octf.SrotBits(a)+ 3) % 4) & ":" & Fmt.Int(SpinBit(a))); } PrintDualPlace_t; void PrintDualwedge(FILE *wr, Wedge_t w, feWidth: uint) Place_t *b; { b = Srot(PlaceInWedge(w, 0)); for (i = 0; i < 4; i++) { PrintDualPlace_t(wr, NextF(b), feWidth); fprintf(wr, " "); b = Srot(b) } } PrintDualwedge; { ??? tp = FileWr.Open(name & ".tp"); ??? vWidth = digits(MAX(1, top->node.ne - 1)); ??? eWidth = digits(MAX(1,top->NE - 1)); ??? fWidth = digits(MAX(1,top->wall.ne - 1)); ??? pWidth = digits(MAX(1,top->cell.ne - 1)); ??? feWidth = digits(MAX(1,top->wall.nelE -1)); { WriteHeader(tp,"topology","99-08-25"); if (((cmt != NULL) && ((*cmt) != 0))) { filefmt_write_comments(tp, cmt & "\n", '|') } ??? m = digits(top->wall.nelE); { fprintf(tp, "nodes "); fprintf(tp, Fmt.Pad(Fmt.Int(top->cell.ne),m) & "\n"); fprintf(tp, "@{edge->?}s "); fprintf(tp, Fmt.Pad(Fmt.Int(top->wall.ne),m) & "\n"); fprintf(tp, "walls "); fprintf(tp, Fmt.Pad(Fmt.Int(top->NE),m) & "\n"); fprintf(tp, "cells "); fprintf(tp, Fmt.Pad(Fmt.Int(top->node.ne),m) & "\n"); fprintf(tp, "wedges "); fprintf(tp, Fmt.Int(top->wall.nelE) & "\n"); fprintf(tp, "der "); fprintf(tp, Fmt.Pad(Fmt.Int(1),m) & "\n"); fprintf(tp, "bdr "); fprintf(tp, Fmt.Pad(Fmt.Int(0),m) & "\n"); } filefmt_write_comments(tp, "\n@{Edge->?} data:\n", '|'); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { fprintf(tp, Fmt.Pad(Fmt.Int(f->num), fWidth)); fprintf(tp, " "); Octf.PrintPlace(tp, f.pa, feWidth); /* [sic] */ fprintf(tp, "\n") } } filefmt_write_comments(tp, "\nWall data:\n", '|'); for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { fprintf(tp, Fmt.Pad(Fmt.Int(e->num), eWidth)); fprintf(tp, " "); Octf.PrintPlace(tp, e.pa, feWidth+1); /* [sic] */ fprintf(tp, "\n") } } filefmt_write_comments(tp, "\nwedge data:\n", '|'); for (i = 0; i < top->wall.nelE; i++) { ??? fe = NARROW(PWedge(top->wedge[i]), Wedge_t); { fprintf(tp, Fmt.Pad(Fmt.Int(fe->num), feWidth)); fprintf(tp, " "); PrintDualwedge(tp, fe, feWidth); fprintf(tp, " "); for (j = 0; j < 4; j++) { ??? n = fe.org[(j+1) % 4]; { TYPECASE n OF break; case NULL: for (i = 0; i < (pWidth-1); i++){ fprintf(tp," "); } fprintf(tp, " - "); | Node(v) ==> fprintf(tp, Fmt.Pad(Fmt.Int(v->num), vWidth) & "p "); | Cell(p) ==> fprintf(tp, Fmt.Pad(Fmt.Int(p->num), pWidth) & "v "); } else { /* nothing */ } } } fprintf(tp, " "); ??? e = fe->edge; { fprintf(tp, Fmt.Pad(Fmt.Int(e->num), eWidth)); } fprintf(tp, "f "); ??? f = fe.wall; { fprintf(tp, Fmt.Pad(Fmt.Int(f->num), fWidth)); } fprintf(tp, "e"); fprintf(tp, "\n"); } } filefmt_write_footer(tp, "topology"); fclose(tp); } } /* END WriteDualTopology */ void WriteStDe( FILE *wr, Coords_t *c, Coords_t *Dc; uint prec /* DF 4 */, char *cmt /* DF "" */) void WriteCoord(double x) { fprintf(wr, Fmt.LongReal(x, Fmt.Style.Sci, prec = prec)) } WriteCoord; void WritePoint(*p: r4_t) { WriteCoord(p[1]); fprintf(wr, " "); WriteCoord(p[0]); fprintf(wr, " "); WriteCoord(p[2]); fprintf(wr, " "); WriteCoord(p[3]); fprintf(wr, " "); } WritePoint; { int NV = (c.ne); ??? d = digits(NV-1); { WriteHeader(wr,"state-derivatives","99-08-25"); filefmt_write_comment(wr, "\n" & cmt & "\n",'|'); fprintf(wr, "nodes == " & Fmt.Int(NV) & "\n"); for (i = 0; i < NV; i++) { fprintf(wr, Fmt.Pad(Fmt.Int(i), d) & ": "); WritePoint(c[i]); fprintf(wr, " "); /* if the derivatives of nodes are zero them writes "0 0 0 0" else writes velocites with the format for write points defined here. */ if ((Dc[i][0] == 0.0) && (Dc[i][1] == 0.0) && (Dc[i][2] == 0.0 AND Dc[i][3] == 0.0 )){ fprintf(wr, "0 0 0 0") } else { WritePoint(Dc[i]) } fprintf(wr, "\n"); } filefmt_write_footer(wr, "state-derivatives"); fprintf(wr, "\n"); fflush(wr); } } /* END WriteStDe */ { } Triangulation. /* /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/Refine.h #ifndef Refine_H #define Refine_H // #TIMESTAMP /* Last edited on 2007-01-25 14:52:01 by stolfi */ /* Tools for refinement of tetrahedra. */ // #INCLUDE // #INCLUDE #include typedef struct ThreePlaces_t { Place_t p[3]; } ThreePlaces_t; vec_typedef(ThreePlaces_vec_t,ThreePlaces_vec,ThreePlaces_t); typedef struct Free { Place_vec_t *tetra; Place_vec_t *octah; } Free; typedef struct Side { Place_vec_t upper; Place_vec_t lower; } Side; typedef struct Corner { Place_vec_t right; Place_vec_t left; Place_vec_t front; Place_vec_t back; } Corner; typedef struct Pack { Side side; Corner corner; } Pack; Place_t MakeBaryTetra(uint order1, uint order2); /* Creates a subdivided tetrahedron, Initializes {self} hangs on the edge component from it a new unglued topological tetrahedron of the given order: {order1 x order2}. [!!! Removed from {Bary.h} !!!] */ Corner MakeTetra(uint order, bool_t net /* DF FALSE */); /* This procedure implements the order-refinement of a topological tetrahedra. See: Relatorio FAPESP numero 5, secao 4.1. The number of new tetrahedra can be compute by the following formula: T(order) == 5/3 order**{3} - 2/3 order, order>= 1. */ ThreePlaces_vec_t *MakeTriang(uint order); Pack MakeLevTe(uint order); Free MakeRowTe(uint order); ThreePlaces_vec_t *MakeRowTriang(uint order); Place_t MakeGluea(uint order); /* Realizes the gluing ca.right <----> cb.left */ Place_t MakeGlueb(uint order); /* Realizes the gluing ca.left <----> cb.right */ Place_t MakeGluec(uint order); /* Realizes the gluing ca.front <----> cb.back */ Place_t MakeGlued(uint order); /* Realizes the gluing ca.back <----> cb.front */ Place_t MakeMaximalGlue(uint order); /* Realizes the maximal glue of a refined tetrahedron */ Place_vec_t *PlacesOnFrontier(Corner *co, uint cnum, uint order); #define Pov_H_copyright \ "Copyright © 2000 Universidade Estadual de Campinas (UNICAMP)" #define Pov_H_author \ "Created by L. P. Lozada, UNICAMP, 2000" \ "Based on tools by R.M.Rosi and J.Stolfi, UNICAMP, 199???" #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/Bary.h #ifndef Bary_H #define Bary_H // #TIMESTAMP /* Last edited on 2007-01-25 14:49:31 by stolfi */ #define Bary_H_copyright \ "Copyright © 2000 State University of Campinas (UNICAMP)." #define Bary_H_author \ "Based on procedures by J. Stolfi and R. M. Rosi, UNICAMP.\n" \ "Extensively modified by L. P. Lozada and J. Stolfi for 3D maps, ca. 2000.\n" // #INCLUDE // #INCLUDE void SetWedgeBaryTetra(Wedge_t w, uint order1, uint order2); /* Creates a new 3D map with the topology of an isolated tetrahedron, an attaches it to the wedge {w}. */ Place_t BaryCorner(Place_t p); /* Argument {p} should be a place on the original map {M}. The result is a place {c} which corresponds to {p}, in the sense that {Org(c) == Org(p)} such that [???] co.e[0] == Corner(p) co.e[1] == Corner(a.Spin) co.e[2] == Corner(a.Srot) co.e[3] == Corner(a.Srot.Spin) co.e[4] == Corner(a.Clock) co.e[5] == Corner(a.Clock.Spin) co.e[6] == Corner(a.Tors) co.e[7] == Corner(a.Tors.Spin) */ Place_t BaryCCorner(Place_t p); /* [???] The place triangulation) {c} belong to topological tetrahedron associated to @place (of Bary) {p}, which has Org(c) == Org(p) and lies onto boundary of tetrahedron such as in one topological tetrahedron to perform: Spin(co.e[1]) == CCorner(p) Spin(co.e[0]) == CCorner(a.Spin) Spin(co.e[3]) == CCorner(a.Srot) Spin(co.e[2]) == CCorner(a.Srot.Spin) Spin(co.e[5]) == CCorner(a.Clock) Spin(co.e[4]) == CCorner(a.Clock.Spin) Spin(co.e[7]) == CCorner(a.Tors) Spin(co.e[6]) == CCorner(a.Tors.Spin) */ void BarySetCorner(Place_t p, Place_t c); void BarySetCCorner(Place_t p, Place_t c); #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/Bary.c /* See {Bary.h} */ // #TIMESTAMP /* Last edited on 2007-01-25 02:51:31 by stolfi */ // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE #include #define Bary_C_copyright \ "Copyright © 2001 Universidade Estadual de Campinas (UNICAMP)" void SetWedgeBaryTetra(Wedge_t w, uint order1, uint order2) { bw->ca = MakeTetraTopo(order1,order2); bw->order1 = order1; bw->order2 = order2; } Place_t BaryCorner(Place_t p) { SRBits_t r = PBits(p); return PWedge(p)->ca.p[r]; } void BarySetCorner(Place_t p, Place_t c) { SRBits_t r = PBits(p); PWedge(p)->ca.p[r] = c; } Place_t BaryCCorner(Place_t p) { SRBits_t r = (PBits(p) ^ 1u); return Spin(PWedge(p)->ca.p[r]); } void BarySetCCorner(Place_t p, Place_t c) { SRBits_t r = (PBits(p) ^ 1u); PWedge(p)->ca.p[r] = Spin(c); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/Refine.c /* See {Refine.h} */ // #INCLUDE #include #include // #INCLUDE // #INCLUDE // #INCLUDE Corner MakeTetra(uint order, bool_t net /* DF FALSE */) { Corner c; CASE order OF break; case 1: return MakeTetra1(net); break; case 2: return MakeTetra2(net); break; case 3: return MakeTetra3(net); break; case 4: return MakeTetra4(net); break; case 5: return MakeTetra5(net); } else { return c; } } /* END MakeTetra */ Trip_vec_t *MakeTriang(uint order) == t : REF ARRAY OF Trip; { CASE order OF break; case 1: return MakeTriang1(); break; case 2: return MakeTriang2(); break; case 3: return MakeTriang3(); break; case 4: return MakeTriang4(); break; case 5: return MakeTriang5(); } else { return t; } } /* END MakeTriang */ Pack MakeLevTe(uint order) Pack *p; { CASE order OF break; case 1: return MakeLevTe1(); break; case 2: return MakeLevTe2(); break; case 3: return MakeLevTe3(); break; case 4: return MakeLevTe4(); break; case 5: return MakeLevTe5(); } else { return p; } } /* END MakeLevTe */ Free MakeRowTe(uint order) Free *f; { CASE order OF break; case 1: return MakeRowTe1(); break; case 2: return MakeRowTe2(); break; case 3: return MakeRowTe3(); break; case 4: return MakeRowTe4(); break; case 5: return MakeRowTe5(); } else { return f; } } /* END MakeRowTe */ Trip_vec_t *MakeRowTriang(uint order) == t : REF ARRAY OF Trip; { CASE order OF break; case 1: return MakeRowTriang1(); break; case 2: return MakeRowTriang2(); break; case 3: return MakeRowTriang3(); break; case 4: return MakeRowTriang4(); break; case 5: return MakeRowTriang5(); } else { return t; } } /* END MakeRowTriang */ Place_t MakeGluea(uint order) { CASE order OF break; case 1: return GlueRefineTetra(0,1,1); break; case 2: return GlueRefineTetra(0,1,2); break; case 3: return GlueRefineTetra(0,1,3); break; case 4: return GlueRefineTetra(0,1,4); break; case 5: return GlueRefineTetra(0,1,5); } else { return Triangulation.MakeWedge(); } } /* END MakeGluea */ Place_t MakeGlueb(uint order) { CASE order OF break; case 1: return GlueRefineTetra(1,0,1); break; case 2: return GlueRefineTetra(1,0,2); break; case 3: return GlueRefineTetra(1,0,3); break; case 4: return GlueRefineTetra(1,0,4); break; case 5: return GlueRefineTetra(1,0,5); } else { return Triangulation.MakeWedge(); } } /* END MakeGlueb */ Place_t MakeGluec(uint order) { CASE order OF break; case 1: return GlueRefineTetra(3,2,1); break; case 2: return GlueRefineTetra(3,2,2); break; case 3: return GlueRefineTetra(3,2,3); break; case 4: return GlueRefineTetra(3,2,4); break; case 5: return GlueRefineTetra(3,2,5); } else { return Triangulation.MakeWedge(); } } /* END MakeGluec */ Place_t MakeGlued(uint order) { CASE order OF break; case 1: return GlueRefineTetra(2,3,1); break; case 2: return GlueRefineTetra(2,3,2); break; case 3: return GlueRefineTetra(2,3,3); break; case 4: return GlueRefineTetra(2,3,4); break; case 5: return GlueRefineTetra(2,3,5); } else { return Triangulation.MakeWedge(); } } /* END MakeGlued */ Corner MakeTetra1(bool_t net = FALSE) Corner *c; { c.right = NEW(REF Place_vec_t,1); c.left = NEW(REF Place_vec_t,1); c.front = NEW(REF Place_vec_t,1); c.back = NEW(REF Place_vec_t,1); ??? a = MakeLevTe1(); { c.right[0] = a.corner.right[0]; c.left [0] = a.corner.left [0]; c.front[0] = a.corner.front[0]; c.back [0] = a.corner.back [0]; /* new extensions */ SetLackNodes(1,c); if (net){ SetGrade(1,c); } return c; } } /* END MakeTetra1 */ Corner MakeTetra2(bool_t net = FALSE) Corner *c; { c.right = NEW(REF Place_vec_t,4); c.left = NEW(REF Place_vec_t,4); c.front = NEW(REF Place_vec_t,4); c.back = NEW(REF Place_vec_t,4); ??? a = MakeTetra1(); ??? b = MakeLevTe2(); { Glue(Spin(b.side.upper[0]), a.back[0],1); HideWall (b.side.upper[0]); for (j = 0; j < 4; j++) { c.back[j] = b.corner.back[j]; } c.right[0] = a.right[0]; c.left [0] = a.left [0]; c.front[0] = a.front[0]; for (i = 1; i < 4; i++) { c.right[i] = b.corner.right[i-1]; c.left [i] = b.corner.left [i-1]; c.front[i] = b.corner.front[i-1]; } /* new extensions */ SetLackNodes(2,c); if (net){ SetGrade(2,c); } return c; } } /* END MakeTetra2 */ Corner MakeTetra3(bool_t net = FALSE) Corner *d; { d.right = NEW(REF Place_vec_t,9); d.left = NEW(REF Place_vec_t,9); d.front = NEW(REF Place_vec_t,9); d.back = NEW(REF Place_vec_t,9); ??? a = MakeTetra2(); ??? c = MakeLevTe3(); { /* Tetra-2 with Level-3: a.back[0]==T with c.upper[0]==O a.back[1]==T with c.upper[1]==O a.back[2]==O with c.upper[2]==T a.back[3]==T with c.upper[3]==O */ assert(((a.back^).ne) == ((c.side.upper^).ne)); EVAL Glue(Spin (a.back[0]), c.side.upper[0], 1, TRUE); HideWall (a.back[0]); EVAL Glue(Spin (a.back[1]), c.side.upper[1], 1, TRUE); HideWall (a.back[1]); EVAL Glue(Clock(a.back[2]), c.side.upper[2], 1, TRUE); HideWall (a.back[2]); Glue(Spin (a.back[3]), c.side.upper[3], 1, TRUE); HideWall (a.back[3]); for (j = 0; j <= (8); j++) { d.back[j] = c.corner.back[j]; } for (i = 0; i < 4; i++) { d.right[i] = a.right[i]; d.left [i] = a.left [i]; d.front[i] = a.front[i]; } for (i = 4; i <= (8); i++) { d.right[i] = c.corner.right[i-4]; d.left [i] = c.corner.left [i-4]; d.front[i] = c.corner.front[i-4]; } /* new extensions */ SetLackNodes(3,d); if (net){ SetGrade(3,d); } return d; } } /* END MakeTetra3 */ Corner MakeTetra4(bool_t net = FALSE) Corner *e; { e.right = NEW(REF Place_vec_t,16); e.left = NEW(REF Place_vec_t,16); e.front = NEW(REF Place_vec_t,16); e.back = NEW(REF Place_vec_t,16); ??? a = MakeTetra3(); ??? d = MakeLevTe4(); { /* gluing Tetra-3 with upper Level-4 */ assert(((a.back^).ne) == ((d.side.upper^).ne)); EVAL Glue(Spin (a.back[0]), d.side.upper[0], 1, TRUE); HideWall (a.back[0]); EVAL Glue(Spin (a.back[1]), d.side.upper[1], 1, TRUE); HideWall (a.back[1]); EVAL Glue(Clock(a.back[2]), d.side.upper[2], 1, TRUE); HideWall (a.back[2]); Glue(Spin (a.back[3]), d.side.upper[3], 1, TRUE); HideWall (a.back[3]); EVAL Glue(Spin (a.back[4]), d.side.upper[4], 1, TRUE); HideWall (a.back[4]); EVAL Glue(Clock(a.back[5]), d.side.upper[5], 1, TRUE); HideWall (a.back[5]); EVAL Glue(Spin (a.back[6]), d.side.upper[6], 1, TRUE); HideWall (a.back[6]); EVAL Glue(Clock(a.back[7]), d.side.upper[7], 1, TRUE); HideWall (a.back[7]); EVAL Glue(Spin (a.back[8]), d.side.upper[8], 1, TRUE); HideWall (a.back[8]); for (j = 0; j <= (15); j++) { e.back[j] = d.corner.back[j]; } for (i = 0; i <= (8); i++) { e.right[i] = a.right[i]; e.left [i] = a.left [i]; e.front[i] = a.front[i]; } for (i = 9; i <= (15); i++) { e.right[i] = d.corner.right[i-9]; e.left [i] = d.corner.left [i-9]; e.front[i] = d.corner.front[i-9]; } /* new extensions */ SetLackNodes(4,e); if (net){ SetGrade(4,e); } return e; } } /* END MakeTetra4 */ Corner MakeTetra5(bool_t net = FALSE) Corner *f; { f.right = NEW(REF Place_vec_t,25); f.left = NEW(REF Place_vec_t,25); f.front = NEW(REF Place_vec_t,25); f.back = NEW(REF Place_vec_t,25); ??? a = MakeTetra4(); ??? e = MakeLevTe5(); { /* gluing Tetra-4 with upper Level-5 */ assert(((a.back^).ne) == ((e.side.upper^).ne)); /* sixteen glues */ /* upper s.upper[0 ] = r2.octah[0,5]; s.upper[1 ] = r3.octah[0,5]; s.upper[2 ] = r3.tetra[3].p[2]; s.upper[3 ] = r3.octah[1,5]; s.upper[4 ] = r4.octah[0,5]; s.upper[5 ] = r4.tetra[5].p[2]; s.upper[6 ] = r4.octah[1,5]; s.upper[7 ] = r4.tetra[4].p[2]; s.upper[8 ] = r4.octah[2,5]; s.upper[9 ] = r5.octah[0,5]; s.upper[10] = r5.tetra[7].p[2]; s.upper[11] = r5.octah[1,5]; s.upper[12] = r5.tetra[5].p[2]; s.upper[13] = r5.octah[2,5]; s.upper[14] = r5.tetra[6].p[2]; s.upper[15] = r5.octah[3,5]; */ /* lower s.lower[0 ] = r1.tetra[0].p[2]; s.lower[1 ] = r2.tetra[0].p[2]; s.lower[2 ] = r2.octah[3,3]; s.lower[3 ] = r2.tetra[1].p[2]; s.lower[4 ] = r3.tetra[0].p[2]; s.lower[5 ] = r3.octah[5,3]; s.lower[6 ] = r3.tetra[1].p[2]; s.lower[7 ] = r3.octah[4,3]; s.lower[8 ] = r3.tetra[2].p[2]; s.lower[9 ] = r4.tetra[0].p[2]; s.lower[10] = r4.octah[0,3]; s.lower[11] = r4.tetra[1].p[2]; s.lower[12] = r4.octah[1,3]; s.lower[13] = r4.tetra[2].p[2]; s.lower[14] = r4.octah[2,3]; s.lower[15] = r4.tetra[3].p[2]; */ EVAL Glue(Spin(a.back[0]), e.side.upper[0], 1, TRUE); HideWall (a.back[0]); EVAL Glue(Spin(a.back[1]), e.side.upper[1], 1, TRUE); HideWall (a.back[1]); EVAL Glue(Clock(a.back[2]), e.side.upper[2], 1, TRUE); HideWall (a.back[2]); EVAL Glue(Spin(a.back[3]), e.side.upper[3], 1, TRUE); HideWall (a.back[3]); EVAL Glue(Spin(a.back[4]), e.side.upper[4], 1, TRUE); HideWall (a.back[4]); EVAL Glue(Clock(a.back[5]), e.side.upper[5], 1, TRUE); HideWall (a.back[5]); EVAL Glue(Spin(a.back[6]), e.side.upper[6], 1, TRUE); HideWall (a.back[6]); EVAL Glue(Clock(a.back[7]), e.side.upper[7], 1, TRUE); HideWall (a.back[7]); EVAL Glue(Spin(a.back[8]), e.side.upper[8], 1, TRUE); HideWall (a.back[8]); EVAL Glue(Spin(a.back[9]), e.side.upper[9], 1, TRUE); HideWall (a.back[9]); EVAL Glue(Clock(a.back[10]), e.side.upper[10], 1, TRUE); HideWall (a.back[10]); EVAL Glue(Spin(a.back[11]), e.side.upper[11], 1, TRUE); HideWall (a.back[11]); EVAL Glue(Clock(a.back[12]), e.side.upper[12], 1, TRUE); HideWall (a.back[12]); EVAL Glue(Spin(a.back[13]), e.side.upper[13], 1, TRUE); HideWall (a.back[13]); EVAL Glue(Clock(a.back[14]), e.side.upper[14], 1, TRUE); HideWall (a.back[14]); EVAL Glue(Spin(a.back[15]), e.side.upper[15], 1, TRUE); HideWall (a.back[15]); for (j = 0; j <= (24); j++) { f.back[j] = e.corner.back[j]; } for (i = 0; i <= (15); i++) { f.right[i] = a.right[i]; f.left [i] = a.left [i]; f.front[i] = a.front[i]; } for (i = 16; i <= (24); i++) { f.right[i] = e.corner.right[i-16]; f.left [i] = e.corner.left [i-16]; f.front[i] = e.corner.front[i-16]; } /* new extensions */ SetLackNodes(5,f); if (net){ SetGrade(5,f); } return f; } } /* END MakeTetra5 */ /* Procedure for builds triangles */ PROCEDURE MakeTriang1() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 1); { ??? t = MakeTriangle(); { r[0] = t; return r; } } /* END MakeTriang1 */ PROCEDURE MakeTriang2() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 4); { ??? t = MakeTriang1(); ??? p = MakeRowTriang2(); { SetNextF (t[0][0], Clock(p[1][0])); SetRingEdgeInfo(t[0][0], PEdge(t[0][0])); SetOrgCycle(t[0][0], OrgV(t[0][0])); SetOrgCycle(Clock(t[0][0]), OrgV(Clock(t[0][0]))); for (j = 0; j < 3; j++) { r[0][j] = t[0][j]; } for (k = 1; k < 4; k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k-1][i]; } } } return r; } /* END MakeTriang2 */ PROCEDURE MakeTriang3() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 9); { ??? t = MakeTriang2(); ??? p = MakeRowTriang3(); { SetNextF (t[1][0], Clock(p[1][0])); SetNextF (t[3][0], Clock(p[3][0])); SetRingEdgeInfo(t[1][0], PEdge(t[1][0])); SetRingEdgeInfo(t[3][0], PEdge(t[3][0])); SetOrgCycle(t[1][0], OrgV(t[1][0])); SetOrgCycle(t[3][0], OrgV(t[3][0])); SetOrgCycle(Clock(t[3][0]), OrgV(Clock(t[3][0]))); for (l = 0; l < 4; l++) { for (j = 0; j < 3; j++) { r[l][j] = t[l][j]; } } for (k = 4; k <= (8); k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k-4][i]; } } } return r; } /* END MakeTriang3 */ PROCEDURE MakeTriang4() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 16); { ??? t = MakeTriang3(); ??? p = MakeRowTriang4(); { SetNextF (t[4][0], Clock(p[1][0])); SetNextF (t[6][0], Clock(p[3][0])); SetNextF (t[8][0], Clock(p[5][0])); SetRingEdgeInfo(t[4][0], PEdge(t[4][0])); SetRingEdgeInfo(t[6][0], PEdge(t[6][0])); SetRingEdgeInfo(t[8][0], PEdge(t[8][0])); SetOrgCycle(t[4][0], OrgV(t[4][0])); SetOrgCycle(t[6][0], OrgV(t[6][0])); SetOrgCycle(t[8][0], OrgV(t[8][0])); SetOrgCycle(Clock(t[8][0]), OrgV(Clock(t[8][0]))); for (l = 0; l <= (8); l++) { for (j = 0; j < 3; j++) { r[l][j] = t[l][j]; } } for (k = 9; k <= (15); k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k-9][i]; } } } return r; } /* END MakeTriang4 */ PROCEDURE MakeTriang5() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 25); { ??? t = MakeTriang4(); ??? p = MakeRowTriang5(); { SetNextF (t[9 ][0], Clock(p[1][0])); SetNextF (t[11][0], Clock(p[3][0])); SetNextF (t[13][0], Clock(p[5][0])); SetNextF (t[15][0], Clock(p[7][0])); SetRingEdgeInfo(t[9 ][0], PWedge(t[9 ][0]).edge); SetRingEdgeInfo(t[11][0], PEdge(t[11][0])); SetRingEdgeInfo(t[13][0], PEdge(t[13][0])); SetRingEdgeInfo(t[15][0], PEdge(t[15][0])); SetOrgCycle(t[9 ][0], OrgV(t[9 ][0])); SetOrgCycle(t[11][0], OrgV(t[11][0])); SetOrgCycle(t[13][0], OrgV(t[13][0])); SetOrgCycle(t[15][0], OrgV(t[15][0])); SetOrgCycle(Clock(t[15][0]), OrgV(Clock(t[15][0]))); for (l = 0; l <= (15); l++) { for (j = 0; j < 3; j++) { r[l][j] = t[l][j]; } } for (k = 16; k <= (24); k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k-16][i]; } } } return r; } /* END MakeTriang5 */ Pack MakeLevTe1() VAR Side s; Corner c; { /* allocating memory */ s.lower = NEW(REF Place_vec_t,1); c.right = NEW(REF Place_vec_t,1); c.left = NEW(REF Place_vec_t,1); c.front = NEW(REF Place_vec_t,1); c.back = NEW(REF Place_vec_t,1); ??? r1 = MakeRowTe1(); { /* computing side information */ s.lower[0] = r1.tetra[0].p[2]; /* computing corner information */ c.right[0] = r1.tetra[0].p[0]; c.left [0] = r1.tetra[0].p[1]; c.front[0] = r1.tetra[0].p[3]; for (i = 0; i <= (0); i++) { c.back [i] = s.lower[i]; } return Pack{s,c}; /* return the base of one tetrahedron /\ / \ /____\ */ } } /* END MakeLevTe1 */ Pack MakeLevTe2() VAR Side s; Corner c; { /* side */ s.upper = NEW(REF Place_vec_t,1); s.lower = NEW(REF Place_vec_t,4); /* corner */ c.right = NEW(REF Place_vec_t,3); c.left = NEW(REF Place_vec_t,3); c.front = NEW(REF Place_vec_t,3); c.back = NEW(REF Place_vec_t,4); ??? r1 = MakeRowTe1(); ??? r2 = MakeRowTe2(); { Glue(Spin(r2.octah[0,7]), Clock(Spin(r1.tetra[0].p[3])),1); HideWall(r2.octah[0,7]); /* computing side information */ s.upper[0] = r2.octah[0,5]; s.lower[0] = r1.tetra[0].p[2]; s.lower[1] = r2.tetra[0].p[2]; s.lower[2] = r2.octah[0,3]; s.lower[3] = r2.tetra[1].p[2]; /* computing corner information */ c.right[0] = r1.tetra[0].p[0]; c.right[1] = r2.octah[0,6]; c.right[2] = r2.tetra[1].p[0]; c.left [0] = r1.tetra[0].p[1]; c.left [1] = r2.octah[0,4]; c.left [2] = r2.tetra[0].p[1]; c.front[0] = r2.tetra[0].p[3]; c.front[1] = r2.octah[0,1]; c.front[2] = r2.tetra[1].p[3]; for (i = 0; i < 4; i++) { c.back [i] = s.lower[i]; } return Pack{s,c}; /* return a single upper triangular wall of the level-2 that will be glue with the single lower triangular wall of the level-1. /\ /\ / \ / \ / 0 \ / 0 \ /------\ ------ / \ 2 / \ / 1 \ / 3 \ /_____\/_____\ s.lower s.upper */ } } /* END MakeLevTe2 */ Pack MakeLevTe3() VAR Side s; Corner c; { /* side */ s.upper = NEW(REF Place_vec_t,4); s.lower = NEW(REF Place_vec_t,9); /* corner */ c.right = NEW(REF Place_vec_t,5); c.left = NEW(REF Place_vec_t,5); c.front = NEW(REF Place_vec_t,5); c.back = NEW(REF Place_vec_t,9); ??? r1 = MakeRowTe1(); ??? r2 = MakeRowTe2(); ??? r3 = MakeRowTe3(); { /* free @places r3.tetra[3].p[3] ==> r2.octah[0,1] r3.octah[0,7] ==> r2.tetra[0].p[3] r3.octah[1,7] ==> r2.tetra[1].p[3] r2.octah[0,7] ==> r1.tetra[0].p[3] */ Glue(Spin (r3.tetra[3].p[3]), r2.octah[0,1], 1); HideWall (r3.tetra[3].p[3]); Glue(Clock(r3.octah[0,7]), r2.tetra[0].p[3], 1); HideWall (r3.octah[0,7]); Glue(Clock(r3.octah[1,7]), r2.tetra[1].p[3], 1); HideWall (r3.octah[1,7]); Glue(Clock(r2.octah[0,7]), r1.tetra[0].p[3], 1); HideWall (r2.octah[0,7]); /* computing side information */ /* upper */ s.upper[0] = r2.octah[0,5]; s.upper[1] = r3.octah[0,5]; s.upper[2] = r3.tetra[3].p[2]; s.upper[3] = r3.octah[1,5]; /* lower */ s.lower[0] = r1.tetra[0].p[2]; s.lower[1] = r2.tetra[0].p[2]; s.lower[2] = r2.octah[0,3]; s.lower[3] = r2.tetra[1].p[2]; s.lower[4] = r3.tetra[0].p[2]; s.lower[5] = r3.octah[0,3]; s.lower[6] = r3.tetra[1].p[2]; s.lower[7] = r3.octah[1,3]; s.lower[8] = r3.tetra[2].p[2]; /* computing corner information */ c.right[0] = r1.tetra[0].p[0]; c.right[1] = r2.octah[0,6]; c.right[2] = r2.tetra[1].p[0]; c.right[3] = r3.octah[1,6]; c.right[4] = r3.tetra[2].p[0]; c.left [0] = r1.tetra[0].p[1]; c.left [1] = r2.octah[0,4]; c.left [2] = r2.tetra[0].p[1]; c.left [3] = r3.octah[0,4]; c.left [4] = r3.tetra[0].p[1]; c.front[0] = r3.tetra[0].p[3]; c.front[1] = r3.octah[0,1]; c.front[2] = r3.tetra[1].p[3]; c.front[3] = r3.octah[1,1]; c.front[4] = r3.tetra[2].p[3]; for (i = 0; i <= (8); i++) { c.back [i] = s.lower[i]; } return Pack{s,c}; /* return an array of (four) upper triangular walls of the level three that will be glue with the (four) lower triangular walls of the level two. /\ /\ / \ / \ / 0 \ / 0 \ /------\ /------\ / \ 2 / \ / \ 2 / \ / 1 \ / 3 \ / 1 \ / 3 \ /_____\/_____\ /_____\/_____\ / 5 / \ 7 / \ / \ / \ / \ / 4 \/ 6 \/ 8 \ -------------------- s.upper s.lower */ } } /* END MakeLevTe3 */ Pack MakeLevTe4() VAR Side s; Corner c; { /* side */ s.upper = NEW(REF Place_vec_t,9); s.lower = NEW(REF Place_vec_t,16); /* corner */ c.right = NEW(REF Place_vec_t,7); c.left = NEW(REF Place_vec_t,7); c.front = NEW(REF Place_vec_t,7); c.back = NEW(REF Place_vec_t,16); ??? r1 = MakeRowTe1(); ??? r2 = MakeRowTe2(); ??? r3 = MakeRowTe3(); ??? r4 = MakeRowTe4(); { /* r1 with r2 */ Glue(Clock(r2.octah[0,7]), r1.tetra[0].p[3], 1); HideWall (r2.octah[0,7]); /* free @places r2 with r3 r3.tetra[3].p[3] ==> r2.octah[0,1] r3.octah[0,7] ==> r2.tetra[0].p[3] r3.octah[1,7] ==> r2.tetra[1].p[3] free @places r2 with r1 r2.octah[0,7] ==> r1.tetra[0].p[3] */ /* r3 with r2 */ Glue(Spin (r3.tetra[3].p[3]), r2.octah[0,1], 1); HideWall (r3.tetra[3].p[3]); Glue(Clock(r3.octah[0,7]), r2.tetra[0].p[3], 1); HideWall (r3.octah[0,7]); Glue(Clock(r3.octah[1,7]), r2.tetra[1].p[3], 1); HideWall (r3.octah[1,7]); /* r4 with r3 */ /* free @places r3 with r2 r4.octah[0,7] ==> r3.tetra[0].p[3] r4.tetra[5].p[3] ==> r3.octah[0,1] r4.octah[1,7] ==> r3.tetra[1].p[3] r4.tetra[1].p[3] ==> r3.octah[1,1] r4.octah[2,7] ==> r3.tetra[2].p[3] */ EVAL Glue(Spin (r4.tetra[5].p[3]), r3.octah[0,1], 1, TRUE); HideWall (r4.tetra[5].p[3]); EVAL Glue(Clock(r4.octah[0,7]), r3.tetra[0].p[3], 1, TRUE); HideWall (r4.octah[0,7]); EVAL Glue(Clock(r4.octah[1,7]), r3.tetra[1].p[3], 1, TRUE); HideWall (r4.octah[1,7]); EVAL Glue(Spin (r4.tetra[4].p[3]), r3.octah[1,1], 1, TRUE); HideWall (r4.tetra[4].p[3]); EVAL Glue(Clock(r4.octah[2,7]), r3.tetra[2].p[3], 1, TRUE); HideWall (r4.octah[2,7]); /* upper */ s.upper[0] = r2.octah[0,5]; s.upper[1] = r3.octah[0,5]; s.upper[2] = r3.tetra[3].p[2]; s.upper[3] = r3.octah[1,5]; s.upper[4] = r4.octah[0,5]; s.upper[5] = r4.tetra[5].p[2]; s.upper[6] = r4.octah[1,5]; s.upper[7] = r4.tetra[4].p[2]; s.upper[8] = r4.octah[2,5]; /* lower */ s.lower[0 ] = r1.tetra[0].p[2]; s.lower[1 ] = r2.tetra[0].p[2]; s.lower[2 ] = r2.octah[0,3]; s.lower[3 ] = r2.tetra[1].p[2]; s.lower[4 ] = r3.tetra[0].p[2]; s.lower[5 ] = r3.octah[0,3]; s.lower[6 ] = r3.tetra[1].p[2]; s.lower[7 ] = r3.octah[1,3]; s.lower[8 ] = r3.tetra[2].p[2]; s.lower[9 ] = r4.tetra[0].p[2]; s.lower[10] = r4.octah[0,3]; s.lower[11] = r4.tetra[1].p[2]; s.lower[12] = r4.octah[1,3]; s.lower[13] = r4.tetra[2].p[2]; s.lower[14] = r4.octah[2,3]; s.lower[15] = r4.tetra[3].p[2]; /* computing corner information */ c.right[0] = r1.tetra[0].p[0]; c.right[1] = r2.octah[0,6]; c.right[2] = r2.tetra[1].p[0]; c.right[3] = r3.octah[1,6]; c.right[4] = r3.tetra[2].p[0]; c.right[5] = r4.octah[2,6]; c.right[6] = r4.tetra[3].p[0]; c.left [0] = r1.tetra[0].p[1]; c.left [1] = r2.octah[0,4]; c.left [2] = r2.tetra[0].p[1]; c.left [3] = r3.octah[0,4]; c.left [4] = r3.tetra[0].p[1]; c.left [5] = r4.octah[0,4]; c.left [6] = r4.tetra[0].p[1]; c.front[0] = r4.tetra[0].p[3]; c.front[1] = r4.octah[0,1]; c.front[2] = r4.tetra[1].p[3]; c.front[3] = r4.octah[1,1]; c.front[4] = r4.tetra[2].p[3]; c.front[5] = r4.octah[2,1]; c.front[6] = r4.tetra[3].p[3]; for (i = 0; i <= (15); i++) { c.back [i] = s.lower[i]; } return Pack{s,c}; /* return an array of (nine) upper triangular walls of the level three that will be glue with the (nine) lower triangular walls of the level three. /\ /\ / \ / \ / 0 \ / 0 \ /------\ /------\ / \ 2 / \ / \ 2 / \ / 1 \ / 3 \ / 1 \ / 3 \ /_____\/_____\ /_____\/_____\ /\ 5 / \ 7 / \ / 5 / \ 7 / \ / \ / \ / \ / \ / \ / \ / 4 \/ 6 \/ 8 \ / 4 \/ 6 \/ 8 \ /--------------------\ --------------------- / \ 10 /\ 12 /\ 14 / \ / \ / \ / \ / \ / 9 \/ 11 \ / 13 \/ 15 \ ---------------------------- s.lower s.upper */ } } /* END MakeLevTe4 */ Pack MakeLevTe5() VAR Side s; Corner c; { /* side */ s.upper = NEW(REF Place_vec_t,16); s.lower = NEW(REF Place_vec_t,25); /* corner */ c.right = NEW(REF Place_vec_t,9); c.left = NEW(REF Place_vec_t,9); c.front = NEW(REF Place_vec_t,9); c.back = NEW(REF Place_vec_t,25); ??? r1 = MakeRowTe1(); ??? r2 = MakeRowTe2(); ??? r3 = MakeRowTe3(); ??? r4 = MakeRowTe4(); ??? r5 = MakeRowTe5(); { /* r1 with r2 */ Glue(Clock(r2.octah[0,7]), r1.tetra[0].p[3], 1); HideWall (r2.octah[0,7]); /* free @places r2 with r3 r3.tetra[3].p[3] ==> r2.octah[0,1] r3.octah[0,7] ==> r2.tetra[0].p[3] r3.octah[1,7] ==> r2.tetra[1].p[3] free @places r2 with r1 r2.octah[0,7] ==> r1.tetra[0].p[3] */ /* r3 with r2 */ Glue(Spin (r3.tetra[3].p[3]), r2.octah[0,1], 1); HideWall (r3.tetra[3].p[3]); Glue(Clock(r3.octah[0,7]), r2.tetra[0].p[3], 1); HideWall (r3.octah[0,7]); Glue(Clock(r3.octah[1,7]), r2.tetra[1].p[3], 1); HideWall (r3.octah[1,7]); /* r4 with r3 */ /* free @places r3 with r2 r4.octah[0,7] ==> r3.tetra[0].p[3] r4.tetra[5].p[3] ==> r3.octah[0,1] r4.octah[1,7] ==> r3.tetra[1].p[3] r4.tetra[1].p[3] ==> r3.octah[1,1] r4.octah[2,7] ==> r3.tetra[2].p[3] */ EVAL Glue(Spin (r4.tetra[5].p[3]), r3.octah[0,1], 1, TRUE); HideWall (r4.tetra[5].p[3]); EVAL Glue(Clock(r4.octah[0,7]), r3.tetra[0].p[3], 1, TRUE); HideWall (r4.octah[0,7]); EVAL Glue(Clock(r4.octah[1,7]), r3.tetra[1].p[3], 1, TRUE); HideWall (r4.octah[1,7]); EVAL Glue(Spin (r4.tetra[4].p[3]), r3.octah[1,1], 1, TRUE); HideWall (r4.tetra[4].p[3]); EVAL Glue(Clock(r4.octah[2,7]), r3.tetra[2].p[3], 1, TRUE); HideWall (r4.octah[2,7]); /* r4 with r5 */ EVAL Glue(Spin (r5.tetra[7].p[3]), r4.octah[0,1], 1, TRUE); HideWall (r5.tetra[7].p[3]); EVAL Glue(Spin (r5.tetra[5].p[3]), r4.octah[1,1], 1, TRUE); HideWall (r5.tetra[5].p[3]); EVAL Glue(Clock(r5.octah[0,7]), r4.tetra[0].p[3], 1, TRUE); HideWall (r5.octah[0,7]); EVAL Glue(Clock(r5.octah[1,7]), r4.tetra[1].p[3], 1, TRUE); HideWall (r5.octah[1,7]); EVAL Glue(Spin (r5.tetra[6].p[3]), r4.octah[2,1], 1, TRUE); HideWall (r5.tetra[6].p[3]); EVAL Glue(Clock(r5.octah[2,7]), r4.tetra[2].p[3], 1, TRUE); HideWall (r5.octah[2,7]); EVAL Glue(Clock(r5.octah[3,7]), r4.tetra[3].p[3], 1, TRUE); HideWall (r5.octah[3,7]); /* computing corner information */ /* upper */ s.upper[0 ] = r2.octah[0,5]; s.upper[1 ] = r3.octah[0,5]; s.upper[2 ] = r3.tetra[3].p[2]; s.upper[3 ] = r3.octah[1,5]; s.upper[4 ] = r4.octah[0,5]; s.upper[5 ] = r4.tetra[5].p[2]; s.upper[6 ] = r4.octah[1,5]; s.upper[7 ] = r4.tetra[4].p[2]; s.upper[8 ] = r4.octah[2,5]; s.upper[9 ] = r5.octah[0,5]; s.upper[10] = r5.tetra[7].p[2]; s.upper[11] = r5.octah[1,5]; s.upper[12] = r5.tetra[5].p[2]; s.upper[13] = r5.octah[2,5]; s.upper[14] = r5.tetra[6].p[2]; s.upper[15] = r5.octah[3,5]; /* lower */ s.lower[0 ] = r1.tetra[0].p[2]; s.lower[1 ] = r2.tetra[0].p[2]; s.lower[2 ] = r2.octah[0,3]; s.lower[3 ] = r2.tetra[1].p[2]; s.lower[4 ] = r3.tetra[0].p[2]; s.lower[5 ] = r3.octah[0,3]; s.lower[6 ] = r3.tetra[1].p[2]; s.lower[7 ] = r3.octah[1,3]; s.lower[8 ] = r3.tetra[2].p[2]; s.lower[9 ] = r4.tetra[0].p[2]; s.lower[10] = r4.octah[0,3]; s.lower[11] = r4.tetra[1].p[2]; s.lower[12] = r4.octah[1,3]; s.lower[13] = r4.tetra[2].p[2]; s.lower[14] = r4.octah[2,3]; s.lower[15] = r4.tetra[3].p[2]; s.lower[16] = r5.tetra[0].p[2]; s.lower[17] = r5.octah[0,3]; s.lower[18] = r5.tetra[1].p[2]; s.lower[19] = r5.octah[1,3]; s.lower[20] = r5.tetra[2].p[2]; s.lower[21] = r5.octah[2,3]; s.lower[22] = r5.tetra[3].p[2]; s.lower[23] = r5.octah[3,3]; s.lower[24] = r5.tetra[4].p[2]; /* computing corner information */ c.right[0] = r1.tetra[0].p[0]; c.right[1] = r2.octah[0,6]; c.right[2] = r2.tetra[1].p[0]; c.right[3] = r3.octah[1,6]; c.right[4] = r3.tetra[2].p[0]; c.right[5] = r4.octah[2,6]; c.right[6] = r4.tetra[3].p[0]; c.right[7] = r5.octah[3,6]; c.right[8] = r5.tetra[4].p[0]; c.left [0] = r1.tetra[0].p[1]; c.left [1] = r2.octah[0,4]; c.left [2] = r2.tetra[0].p[1]; c.left [3] = r3.octah[0,4]; c.left [4] = r3.tetra[0].p[1]; c.left [5] = r4.octah[0,4]; c.left [6] = r4.tetra[0].p[1]; c.left [7] = r5.octah[0,4]; c.left [8] = r5.tetra[0].p[1]; c.front[0] = r5.tetra[0].p[3]; c.front[1] = r5.octah[0,1]; c.front[2] = r5.tetra[1].p[3]; c.front[3] = r5.octah[1,1]; c.front[4] = r5.tetra[2].p[3]; c.front[5] = r5.octah[2,1]; c.front[6] = r5.tetra[3].p[3]; c.front[7] = r5.octah[3,1]; c.front[8] = r5.tetra[4].p[3]; for (i = 0; i <= (24); i++) { c.back [i] = s.lower[i]; } return Pack{s,c}; /* return an array of (sixteen) upper triangular walls of the level three that will be glue with the (sixteen) lower triangular walls of the level four. /\ /\ / \ / \ / 0 \ / 0 \ /------\ /------\ / \ 2 / \ / \ 2 / \ / 1 \ / 3 \ / 1 \ / 3 \ /_____\/_____\ /_____\/_____\ /\ 5 / \ 7 / \ / 5 / \ 7 / \ / \ / \ / \ / \ / \ / \ / 4 \/ 6 \/ 8 \ / 4 \/ 6 \/ 8 \ --------------------\ --------------------- / \ 10 /\ 12 /\ 14 / \ / \ / \ / \ / \ / 9 \/ 11 \ / 13 \/ 15 \ ---------------------------- s.upper s.upper */ } } /* END MakeLevTe5 */ Free MakeRowTe1() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t,1,4); ??? t = MakeTetraTopo(1,1); { for (i = 0; i < 4; i++) { f.tetra[0].p[i] = t[i]; } return f; /* return one triangular */; } } /* END MakeRowTe1 */ Free MakeRowTe2() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t,2,4); f.octah = NEW(REF ARRAY OF Place_vec_t,1,8); ??? p = GlueTetraOctah(); ??? t = MakeTetraTopo(1,1); { Glue(Clock(p.octah[0,2]), t[1], 1); HideWall(p.octah[0,2]); for (i = 0; i < 4; i++) { f.tetra[0].p[i] = p.tetra[0].p[i]; } for (i = 0; i < 4; i++) { f.tetra[1].p[i] = t[i]; } for (i = 0; i < 8; i++) { f.octah[0,i] = p.octah[0,i]; } return f; } } /* END MakeRowTe2 */ Free GlueTetraOctah() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t,1,4); f.octah = NEW(REF ARRAY OF Place_vec_t,1,8); ??? t = MakeTetraTopo(1,1); ??? o = Squared.MakeOctahedronTriang(TRUE); { Glue(Spin(o[0]), t[0], 1); HideWall(o[0]); for (i = 0; i < 4; i++) { f.tetra[0].p[i] = t[i]; } for (j = 0; j < 8; j++) { f.octah[0,j] = o[j]; } return f; } } /* END GlueTetraOctah */ Free MakeRowTe3() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t,4,4); f.octah = NEW(REF ARRAY OF Place_vec_t,2,8); ??? r2 = MakeRowTe2(); ??? r1 = GlueTetraOctah(); ??? t = MakeTetraTopo(1,1); { /* free @places: r1.octah [0,2] and t[0] r2.tetra[0].p[1] and r2.octah[0,4] */ Glue(Spin(r2.octah[0,4]) , Clock(Spin(t[0])), 1); HideWall(r2.octah[0,4]); Glue(Spin(t[1]) , r1.octah[0,6], 1); HideWall(t[1]); Glue(Clock(r1.octah[0,2]), r2.tetra[0].p[1], 1); HideWall(r1.octah[0,2]); for (i = 0; i < 4; i++) { f.tetra[0].p[i] = r1.tetra[0].p[i]; f.tetra[1].p[i] = r2.tetra[0].p[i]; f.tetra[2].p[i] = r2.tetra[1].p[i]; f.tetra[3].p[i] = t[i]; } for (i = 0; i < 8; i++) { f.octah[0,i] = r1.octah[0,i]; f.octah[1,i] = r2.octah[0,i]; } return f; } } /* END MakeRowTe3 */ Free MakeRowTe4() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t,6,4); f.octah = NEW(REF ARRAY OF Place_vec_t,3,8); ??? r3 = MakeRowTe3(); ??? r1 = GlueTetraOctah(); ??? t = MakeTetraTopo(1,1); { /* free @places: r1.octah[0,2] and t[0] r3.tetra[0].p[1] and r3.octah[0,4] */ Glue(Spin(r3.octah[0,4]) , Spin(Clock(t[0])), 1); HideWall (r3.octah[0,4]); Glue(Spin(t[1]) , r1.octah[0,6], 1); HideWall (t[1]); Glue(Clock(r1.octah[0,2]), r3.tetra[0].p[1], 1); HideWall (r1.octah[0,2]); for (i = 0; i < 4; i++) { f.tetra[0].p[i] = r1.tetra[0].p[i]; f.tetra[1].p[i] = r3.tetra[0].p[i]; f.tetra[2].p[i] = r3.tetra[1].p[i]; f.tetra[3].p[i] = r3.tetra[2].p[i]; f.tetra[4].p[i] = r3.tetra[3].p[i]; f.tetra[5].p[i] = t[i]; } for (i = 0; i < 8; i++) { f.octah[0,i] = r1.octah[0,i]; f.octah[1,i] = r3.octah[0,i]; f.octah[2,i] = r3.octah[1,i]; } return f; } } /* END MakeRowTe4 */ Free MakeRowTe5() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t,8,4); f.octah = NEW(REF ARRAY OF Place_vec_t,5,8); ??? r3 = MakeRowTe4(); ??? r1 = GlueTetraOctah(); ??? t = MakeTetraTopo(1,1); { /* free @places: r1.octah[0,2] and t[0] r3.tetra[0].p[1] and r3.octah[0,4] */ Glue(Spin(r3.octah[0,4]) , Spin(Clock(t[0])),1); HideWall (r3.octah[0,4]); Glue(Spin(t[1]) , r1.octah[0,6], 1); HideWall (t[1]); Glue(Clock(r1.octah[0,2]), r3.tetra[0].p[1], 1); HideWall (r1.octah[0,2]); for (i = 0; i < 4; i++) { f.tetra[0].p[i] = r1.tetra[0].p[i]; f.tetra[1].p[i] = r3.tetra[0].p[i]; f.tetra[2].p[i] = r3.tetra[1].p[i]; f.tetra[3].p[i] = r3.tetra[2].p[i]; f.tetra[4].p[i] = r3.tetra[3].p[i]; f.tetra[5].p[i] = r3.tetra[5].p[i]; f.tetra[6].p[i] = r3.tetra[4].p[i]; f.tetra[7].p[i] = t[i]; } for (i = 0; i < 8; i++) { f.octah[0,i] = r1.octah[0,i]; f.octah[1,i] = r3.octah[0,i]; f.octah[2,i] = r3.octah[1,i]; f.octah[3,i] = r3.octah[2,i]; } return f; } } /* END MakeRowTe5 */ PROCEDURE MakeRowTriang1() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 1); { ??? t = MakeTriangle(); { r[0] = t; return r; } } /* END MakeRowTriang1 */ PROCEDURE MakeRowTriang2() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 3); { ??? p = GlueTwoTriang(); ??? t = MakeRowTriang1(); { SetNextF (p[1][2], Clock(t[0][2])); SetRingEdgeInfo(p[1][2], PEdge(p[1][2])); SetOrg(t[0][2], OrgV(Clock(p[1][2]))); SetOrg(Clock(t[0][2]), OrgV(p[1][2])); SetOrg(Clock(t[0][1]), OrgV(t[0][2])); SetOrg( t[0][0] , OrgV(Clock(t[0][2]))); for (k = 0; k < 2; k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k][i]; } } for (j = 0; j < 3; j++) { r[2][j] = t[0][j]; } } return r; } /* END MakeRowTriang2 */ PROCEDURE MakeRowTriang3() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 5); { ??? p = GlueTwoTriang(); ??? t = MakeRowTriang2(); { SetNextF (p[1][2], Clock(t[0][2])); SetRingEdgeInfo(p[1][2], PEdge(p[1][2])); SetOrg(t[0][2], OrgV(Clock(p[1][2]))); SetOrg(Clock(t[0][2]), OrgV(p[1][2])); SetOrg( t[0][0] , OrgV(Clock(t[0][2]))); SetOrgCycle(Clock(t[0][1]), OrgV(t[0][2])); for (k = 0; k < 2; k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k][i]; } } for (k = 2; k < 5; k++) { for (j = 0; j < 3; j++) { r[k][j] = t[k-2][j]; } } } return r; } /* END MakeRowTriang3 */ PROCEDURE MakeRowTriang4() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 7); { ??? p = GlueTwoTriang(); ??? t = MakeRowTriang3(); { SetNextF (p[1][2], Clock(t[0][2])); SetRingEdgeInfo(p[1][2], PEdge(p[1][2])); SetOrg(t[0][2], OrgV(Clock(p[1][2]))); SetOrg(Clock(t[0][2]), OrgV(p[1][2])); SetOrg( t[0][0] , OrgV(Clock(t[0][2]))); SetOrgCycle(Clock(t[0][1]), OrgV(t[0][2])); for (k = 0; k < 2; k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k][i]; } } for (k = 2; k <= (6); k++) { for (j = 0; j < 3; j++) { r[k][j] = t[k-2][j]; } } } return r; } /* END MakeRowTriang4 */ PROCEDURE MakeRowTriang5() : REF ARRAY OF Trip == r = NEW(REF ARRAY OF Trip, 9); { ??? p = GlueTwoTriang(); ??? t = MakeRowTriang4(); { SetNextF (p[1][2], Clock(t[0][2])); SetRingEdgeInfo(p[1][2], PEdge(p[1][2])); SetOrg(t[0][2], OrgV(Clock(p[1][2]))); SetOrg(Clock(t[0][2]), OrgV(p[1][2])); SetOrg( t[0][0] , OrgV(Clock(t[0][2]))); SetOrgCycle(Clock(t[0][1]), OrgV(t[0][2])); for (k = 0; k < 2; k++) { for (i = 0; i < 3; i++) { r[k][i] = p[k][i]; } } for (k = 2; k <= (8); k++) { for (j = 0; j < 3; j++) { r[k][j] = t[k-2][j]; } } } return r; } /* END MakeRowTriang5 */ PROCEDURE GlueTwoTriang() : ARRAY [0..1] OF Trip == Trip p[1+1]; { ??? t1 = MakeTriangle(); ??? t2 = MakeTriangle(); { SetNextF(t1[1], Clock(t2[1])); SetRingEdgeInfo(t1[1], PEdge(t1[1])); SetOrg(t2[1], OrgV(Clock(t1[1]))); SetOrg(Clock(t2[1]), OrgV(t1[1])); SetOrg(Clock(t2[0]), OrgV(t2[1])); SetOrg( t2[2], OrgV(Clock(t2[1]))); for (i = 0; i < 3; i++) { p[0][i] = t1[i]; p[1][i] = t2[i]; } } return p; } /* END GlueTwoTriang */ Place_t GlueRefineTetra( uint fa, fb; uint order; ) { if (order == 1){ ??? ca = MakeTetra1(); ??? cb = MakeTetra1(); { if (( fa == 0) && (fb == 1)) { /* must be glue ca.right <--> cb.left */ Glue(Spin(cb.left[0]), ca.right[0], 1); return cb.left[0]; } else if ((fa == 1) && (fb == 0)){ /* must be glue ca.left <--> cb.right */ Glue(Spin(ca.left[0]), cb.right[0], 1); return ca.left[0]; } else if ((fa == 3) && (fb == 2)){ /* must be glue ca.front <--> cb.back */ Glue(Spin(cb.back[0]), ca.front[0], 1); return cb.back[0]; } else if ((fa == 2) && (fb == 3)){ /* must be glue ca.back <--> cb.front */ Glue(Spin(cb.front[0]), ca.back[0], 1); return cb.front[0]; } } } else if (order == 2){ ??? ca = MakeTetra2(); ??? cb = MakeTetra2(); { if (( fa == 0) && (fb == 1)) { /* must be glue ca.right <--> cb.left */ Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } return cb.left[0]; } else if ((fa == 1) && (fb == 0)){ /* must be glue ca.left <--> cb.right */ Glue(Spin(ca.left[0]), cb.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } return ca.left[0]; } else if ((fa == 3) && (fb == 2)){ /* must be glue ca.front <--> cb.back */ Glue(Spin(cb.back[0]), ca.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } return cb.back[0]; } else if ((fa == 2) && (fb == 3)){ /* must be glue ca.front <--> cb.back */ Glue(Spin(ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } } else if (order == 3){ ??? ca = MakeTetra3(); ??? cb = MakeTetra3(); { if (( fa == 0) && (fb == 1)) { /* must be glue ca.right <--> cb.left */ Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } return cb.left[0]; } else if (( fa == 1) && (fb == 0)){ /* must be glue ca.lef <--> cb.right */ Glue(Spin(ca.left[0]), cb.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } return ca.left[0]; } else if ((fa == 3) && (fb == 2)){ /* must be glue ca.front <--> cb.back */ Glue(Spin (cb.back[0]), ca.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } return cb.back[0]; } else if ((fa == 2) && (fb == 3)){ /* must be glue ca.back <--> cb.front */ Glue(Spin (ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } } else if (order == 4){ ??? ca = MakeTetra4(); ??? cb = MakeTetra4(); { if (( fa == 0) && (fb == 1)) { /* must be glue ca.right <--> cb.left */ Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } return cb.left[0]; } else if ((fa == 1) && (fb == 0)){ /* must be glue cb.right <--> ca.left */ Glue(Spin(ca.left[0]), cb.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } return ca.left[0]; } else if ((fa == 3) && (fb == 2)){ /* must be glue ca.front <--> cb.back */ Glue(Spin (cb.back[0]), ca.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } return cb.back[0]; } else if ((fa == 2) && (fb == 3)){ /* must be glue ca.back <--> cb.front */ Glue(Spin (ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } } else if (order == 5){ ??? ca = MakeTetra5(); ??? cb = MakeTetra5(); { if (( fa == 0) && (fb == 1)) { /* must be glue ca.right <--> cb.left */ Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 16; i <= (24); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } return cb.left[0]; } else if ((fa == 1) && (fb == 0)){ /* must be glue cb.right <--> ca.left */ Glue(Spin(ca.left[0]), cb.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } for (i = 16; i <= (24); i++) { if (i % 2 == 0) { Glue(Spin (ca.left[i]), cb.right[i], 1); } else { Glue(Spin (ca.left[i]), Spin(Clock(cb.right[i])), 1); } } return ca.left[0]; } else if ((fa == 3) && (fb == 2)){ /* must be glue ca.front <--> cb.back */ Glue(Spin (cb.back[0]), ca.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } for (i = 16; i <= (24); i++) { if (i % 2 == 0) { Glue(Spin (cb.back[i]), ca.front[i], 1); } else { Glue(Clock(cb.back[i]), ca.front[i], 1); } } return cb.back[0]; ; } else if ((fa == 2) && (fb == 3)){ /* must be glue ca.back <--> cb.front */ Glue(Spin (ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 16; i <= (24); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } } return Triangulation.MakeWedge(); } /* END GlueRefineTetra */ Place_t MakeMaximalGlue(order : uint) { if (order == 1){ ??? ca = MakeTetra1(); ??? cb = MakeTetra1(); { Glue(Spin(cb.left[0]), ca.right[0], 1); Glue(Spin(cb.front[0]), ca.back[0], 1); return cb.front[0]; } } else if (order == 2){ ??? ca = MakeTetra2(); ??? cb = MakeTetra2(); { Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } Glue(Spin(ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } else if (order == 3){ ??? ca = MakeTetra3(); ??? cb = MakeTetra3(); { Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } Glue(Spin (ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } else if (order == 4){ ??? ca = MakeTetra4(); ??? cb = MakeTetra4(); { Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } Glue(Spin (ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } else if (order == 5){ ??? ca = MakeTetra5(); ??? cb = MakeTetra5(); { Glue(Spin(cb.left[0]), ca.right[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } for (i = 16; i <= (24); i++) { if (i % 2 == 0) { Glue(Spin (cb.left[i]), ca.right[i], 1); } else { Glue(Spin (cb.left[i]), Spin(Clock(ca.right[i])), 1); } } Glue(Spin (ca.back[0]), cb.front[0], 1); for (i = 1; i < 4; i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 4; i <= (8); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 9; i <= (15); i++) { if (i % 2!=0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } for (i = 16; i <= (24); i++) { if (i % 2 == 0) { Glue(Spin (ca.back[i]), cb.front[i], 1); } else { Glue(Clock(ca.back[i]), cb.front[i], 1); } } return ca.back[0]; } } return Triangulation.MakeWedge(); } /* END MakeMaximalGlue */ void HideWall(Place_t @p) /* This procedure do the following sets: Walls : PWall(a) = FALSE @{Edge->?}s: PEdge(a) = FALSE PEdge(NextE(a)) = FALSE PEdge(PrevE(a)) = FALSE Nodes: OrgV(a) == FALSE OrgV(NextE(a)) == FALSE OrgV(PrevE(a)) == FALSE */ { Place_t b = NextE(a); Place_t c = PrevE(a); { /* setting wall */ PWall(a)->exists = FALSE; /* setting @{edge->?}s */ PEdge(a)->exists = FALSE; PEdge(b)->exists = FALSE; PEdge(c)->exists = FALSE; /* setting nodes */ OrgV(a)->exists = FALSE; OrgV(a).label = "VF"; OrgV(b)->exists = FALSE; OrgV(c)->exists = FALSE; } } /* END HideWall */ void SetLackNodes(ord: uint; co: Corner) /* Set the lack nodes as existing on the boundary of a refined tetrahedron of order "ord". */ PROCEDURE SetNodesOn@{Edge->?}(Place_t @p) == { ??? r = PWedge(co.right[0]).edge.radius; Node_t v = OrgV(a); { v->exists = TRUE; v.radius = r; v.label = "VE"; } } SetNodesOn@{Edge->?}; { if (ord == 2){ SetNodesOn@{Edge->?}(co.right[0]); SetNodesOn@{Edge->?}(co.right[2]); SetNodesOn@{Edge->?}(co.right[3]); /* */ SetNodesOn@{Edge->?}(Clock(co.left[2])); /* */ SetNodesOn@{Edge->?}(co.left[3]); /* */ SetNodesOn@{Edge->?}(co.front[3]); } else if (ord == 3){ SetNodesOn@{Edge->?}(co.right[0]); SetNodesOn@{Edge->?}(co.right[1]); SetNodesOn@{Edge->?}(co.right[2]); SetNodesOn@{Edge->?}(co.right[7]); SetNodesOn@{Edge->?}(co.right[8]); SetNodesOn@{Edge->?}(co.right[6]); /* */ SetNodesOn@{Edge->?}(Clock(co.left[2])); SetNodesOn@{Edge->?}(Clock(co.left[7])); /* */ SetNodesOn@{Edge->?}(co.left[5]); SetNodesOn@{Edge->?}(co.left[7]); /* */ SetNodesOn@{Edge->?}(co.front[6]); SetNodesOn@{Edge->?}(co.front[8]); } else if (ord == 4){ SetNodesOn@{Edge->?}(co.right[0 ]); SetNodesOn@{Edge->?}(co.right[1 ]); SetNodesOn@{Edge->?}(co.right[4 ]); SetNodesOn@{Edge->?}(co.right[2 ]); SetNodesOn@{Edge->?}(co.right[7 ]); SetNodesOn@{Edge->?}(co.right[14]); SetNodesOn@{Edge->?}(co.right[15]); SetNodesOn@{Edge->?}(co.right[13]); SetNodesOn@{Edge->?}(co.right[11]); /* */ SetNodesOn@{Edge->?}(Clock(co.left[ 2])); SetNodesOn@{Edge->?}(Clock(co.left[ 7])); SetNodesOn@{Edge->?}(Clock(co.left[14])); /* */ SetNodesOn@{Edge->?}(co.left[10]); SetNodesOn@{Edge->?}(co.left[12]); SetNodesOn@{Edge->?}(co.left[14]); /* */ SetNodesOn@{Edge->?}(co.front[11]); SetNodesOn@{Edge->?}(co.front[13]); SetNodesOn@{Edge->?}(co.front[15]); /* setting node label on wall */ } else if (ord == 5){ SetNodesOn@{Edge->?}(co.right[ 0]); SetNodesOn@{Edge->?}(co.right[ 1]); SetNodesOn@{Edge->?}(co.right[ 4]); SetNodesOn@{Edge->?}(co.right[ 9]); SetNodesOn@{Edge->?}(co.right[ 2]); SetNodesOn@{Edge->?}(co.right[ 7]); SetNodesOn@{Edge->?}(co.right[14]); SetNodesOn@{Edge->?}(co.right[23]); SetNodesOn@{Edge->?}(co.right[24]); SetNodesOn@{Edge->?}(co.right[22]); SetNodesOn@{Edge->?}(co.right[20]); SetNodesOn@{Edge->?}(co.right[18]); /* */ SetNodesOn@{Edge->?}(Clock(co.left[ 2])); SetNodesOn@{Edge->?}(Clock(co.left[ 7])); SetNodesOn@{Edge->?}(Clock(co.left[14])); SetNodesOn@{Edge->?}(Clock(co.left[23])); /* */ SetNodesOn@{Edge->?}(co.left[17]); SetNodesOn@{Edge->?}(co.left[19]); SetNodesOn@{Edge->?}(co.left[21]); SetNodesOn@{Edge->?}(co.left[23]); /* */ SetNodesOn@{Edge->?}(co.front[18]); SetNodesOn@{Edge->?}(co.front[20]); SetNodesOn@{Edge->?}(co.front[22]); SetNodesOn@{Edge->?}(co.front[24]); } } /* END SetLackNodes */ void SetGrade(ord: uint; co: Corner) /* Set @{edge->?}s and spheres underling on the boundary of a tetrahedron as thin cylinders and small spheres. */ void SetNodeOnNet(Place_t @p) { Node_t vn = OrgV(a); { vn->exists = TRUE; vn.radius = 0.025; vn.color = (frgb_t){1.00,1.00,0.50}; } } SetNodeOnNet; void SetEdgeOnNet(Place_t @p) { Edge_t en = PEdge(a); { en->exists = TRUE; en.radius = 0.0025; en.color = (frgb_t){1.00,1.00,0.5}; } } SetEdgeOnNet; void SetGrade1() { /* nothing */ } SetGrade1; void SetGrade2() { /* 3 @{edge->?}s and 0 nodes for each wall of the refined tetrahedron. */ /* On the right side. */ SetEdgeOnNet(PrevE(co.right[0])); SetEdgeOnNet( co.right[3]); SetEdgeOnNet(NextE (co.right[2])); /* On the left side. */ SetEdgeOnNet(PrevE(co.left[0])); SetEdgeOnNet( co.left[2]); SetEdgeOnNet(NextE (co.left[1])); /* On the front side. */ SetEdgeOnNet( co.front[0]); SetEdgeOnNet(NextE (co.front[1])); SetEdgeOnNet(NextE (co.front[2])); /* On the back side. */ SetEdgeOnNet( co.back [0]); SetEdgeOnNet(NextE (co.back [1])); SetEdgeOnNet(PrevE(co.back [2])); } SetGrade2; void SetGrade3() { /* 9 @{edge->?}s and 1 nodes for each wall of the refined tetrahedron. */ SetGrade2(); /* On the right side. */ SetEdgeOnNet(PrevE(co.right[3])); SetEdgeOnNet(PrevE(co.right[1])); SetEdgeOnNet( co.right[8]); SetEdgeOnNet(NextE (co.right[7])); SetEdgeOnNet( co.right[6]); SetEdgeOnNet(NextE (co.right[5])); SetNodeOnNet(co.right[3]); /* On the left side. */ SetEdgeOnNet(PrevE(co.left[1])); SetEdgeOnNet(PrevE(co.left[3])); SetEdgeOnNet(NextE (co.left[4])); SetEdgeOnNet( co.left[5]); SetEdgeOnNet(NextE (co.left[6])); SetEdgeOnNet( co.left[7]); SetNodeOnNet(co.left[3]); /* On the front side. */ SetEdgeOnNet( co.front[1]); SetEdgeOnNet( co.front[3]); SetEdgeOnNet(NextE (co.front[4])); SetEdgeOnNet(NextE (co.front[5])); SetEdgeOnNet(NextE (co.front[6])); SetEdgeOnNet(NextE (co.front[7])); SetNodeOnNet(co.front[3]); /* On the back side. */ SetEdgeOnNet( co.back [1]); SetEdgeOnNet( co.back [3]); SetEdgeOnNet(NextE (co.back [4])); SetEdgeOnNet(PrevE(co.back [5])); SetEdgeOnNet(NextE (co.back [6])); SetEdgeOnNet(PrevE(co.back [7])); SetNodeOnNet(co.back[3]); } SetGrade3; void SetGrade4() { /* 18 @{edge->?}s and 3 nodes for each wall of the refined tetrahedron. */ SetGrade3(); /* On the right side. */ SetEdgeOnNet(PrevE(co.right[8])); SetEdgeOnNet(PrevE(co.right[6])); SetEdgeOnNet(PrevE(co.right[4])); SetEdgeOnNet( co.right[15]); SetEdgeOnNet(NextE (co.right[14])); SetEdgeOnNet( co.right[13]); SetEdgeOnNet(NextE (co.right[12])); SetEdgeOnNet( co.right[11]); SetEdgeOnNet(NextE (co.right[10])); SetNodeOnNet(co.right[8]); SetNodeOnNet(co.right[6]); /* On the left side. */ SetEdgeOnNet(PrevE(co.left[4])); SetEdgeOnNet(PrevE(co.left[6])); SetEdgeOnNet(PrevE(co.left[8])); SetEdgeOnNet(NextE (co.left[9 ])); SetEdgeOnNet( co.left[10]); SetEdgeOnNet(NextE (co.left[11])); SetEdgeOnNet( co.left[12]); SetEdgeOnNet(NextE (co.left[13])); SetEdgeOnNet( co.left[14]); SetNodeOnNet(co.left[8]); SetNodeOnNet(co.left[6]); /* On the front side. */ SetEdgeOnNet( co.front[4]); SetEdgeOnNet( co.front[6]); SetEdgeOnNet( co.front[8]); SetEdgeOnNet(NextE (co.front[ 9])); SetEdgeOnNet(NextE (co.front[10])); SetEdgeOnNet(NextE (co.front[11])); SetEdgeOnNet(NextE (co.front[12])); SetEdgeOnNet(NextE (co.front[13])); SetEdgeOnNet(NextE (co.front[14])); SetNodeOnNet(co.front[8]); SetNodeOnNet(co.front[6]); /* On the back side. */ SetEdgeOnNet( co.back [4]); SetEdgeOnNet( co.back [6]); SetEdgeOnNet( co.back [8]); SetEdgeOnNet(NextE (co.back [ 9])); SetEdgeOnNet(PrevE(co.back [10])); SetEdgeOnNet(NextE (co.back [11])); SetEdgeOnNet(PrevE(co.back [12])); SetEdgeOnNet(NextE (co.back [13])); SetEdgeOnNet(PrevE(co.back [14])); SetNodeOnNet(co.back[8]); SetNodeOnNet(co.back[6]); } SetGrade4; void SetGrade5() { /* 10 @{edge->?}s and 6 nodes for each wall of the refined tetrahedron. */ SetGrade4(); /* On the right side. */ SetEdgeOnNet(PrevE(co.right[15])); SetEdgeOnNet(PrevE(co.right[13])); SetEdgeOnNet(PrevE(co.right[11])); SetEdgeOnNet(PrevE(co.right[ 9])); SetEdgeOnNet( co.right[24]); SetEdgeOnNet(NextE (co.right[23])); SetEdgeOnNet( co.right[22]); SetEdgeOnNet(NextE (co.right[21])); SetEdgeOnNet( co.right[20]); SetEdgeOnNet(NextE (co.right[19])); SetEdgeOnNet( co.right[18]); SetEdgeOnNet(NextE (co.right[17])); SetNodeOnNet(co.right[15]); SetNodeOnNet(co.right[13]); SetNodeOnNet(co.right[11]); /* On the left side. */ SetEdgeOnNet(PrevE(co.left[ 9])); SetEdgeOnNet(PrevE(co.left[11])); SetEdgeOnNet(PrevE(co.left[13])); SetEdgeOnNet(PrevE(co.left[15])); SetEdgeOnNet(NextE (co.left[16])); SetEdgeOnNet( co.left[17]); SetEdgeOnNet(NextE (co.left[18])); SetEdgeOnNet( co.left[19]); SetEdgeOnNet(NextE (co.left[20])); SetEdgeOnNet( co.left[21]); SetEdgeOnNet(NextE (co.left[22])); SetEdgeOnNet( co.left[23]); SetNodeOnNet(co.left[15]); SetNodeOnNet(co.left[13]); SetNodeOnNet(co.left[11]); /* On the front side. */ SetEdgeOnNet( co.front[ 9]); SetEdgeOnNet( co.front[11]); SetEdgeOnNet( co.front[13]); SetEdgeOnNet( co.front[15]); SetEdgeOnNet(NextE (co.front[16])); SetEdgeOnNet(NextE (co.front[17])); SetEdgeOnNet(NextE (co.front[18])); SetEdgeOnNet(NextE (co.front[19])); SetEdgeOnNet(NextE (co.front[20])); SetEdgeOnNet(NextE (co.front[21])); SetEdgeOnNet(NextE (co.front[22])); SetEdgeOnNet(NextE (co.front[23])); SetNodeOnNet(co.front[15]); SetNodeOnNet(co.front[13]); SetNodeOnNet(co.front[11]); /* On the back side. */ SetEdgeOnNet( co.back [ 9]); SetEdgeOnNet( co.back [11]); SetEdgeOnNet( co.back [13]); SetEdgeOnNet( co.back [15]); SetEdgeOnNet(NextE (co.back [16])); SetEdgeOnNet(PrevE(co.back [17])); SetEdgeOnNet(NextE (co.back [18])); SetEdgeOnNet(PrevE(co.back [19])); SetEdgeOnNet(NextE (co.back [20])); SetEdgeOnNet(PrevE(co.back [21])); SetEdgeOnNet(NextE (co.back [22])); SetEdgeOnNet(PrevE(co.back [23])); SetNodeOnNet(co.back[15]); SetNodeOnNet(co.back[13]); SetNodeOnNet(co.back[11]); } SetGrade5; { if ( ord == 1){ SetGrade1(); } else if (ord == 2){ SetGrade2(); } else if (ord == 3){ SetGrade3(); } else if (ord == 4){ SetGrade4(); } else if (ord == 5){ SetGrade5(); } else { fprintf(stderr,"Order must be less equal to 5\n"); assert(ord <= 5); } } /* END SetGrade */ PROCEDURE MakeTriangle() : ARRAY [0..2] OF Place_t == /* Builds a triangular wall and set the three places with the same wall component. */ Place_t t[2+1]; { Place_t a = MakeWedge(); Place_t b = MakeWedge(); Place_t c = MakeWedge(); Wall_t f = PWall(a); Node_t u = MakeNode(); Node_t v = MakeNode(); Node_t w = MakeNode(); { SetOrg(a, u); SetOrg(Clock(a),v); SetNextE(a,b); SetWallInfo(b,f); SetOrg(b,v); SetOrg(Clock(b),w); SetNextE(b,c); SetWallInfo(c,f); SetOrg(c, w); SetOrg(Clock(c), OrgV(a)); assert(NextE(c) == a); t[0] = a; t[1] = b; t[2] = c; return t; } } /* END MakeTriangle */ void SetOrgCycle(Place_t @p, n: Node) /* Set all @places adjacent to "a" and underling on the 2D star of the node {n} with this node. */ void SetOrgWall(b: Place_t) /* Set all @places adjacent to "a" on the NextF's ring with the node {n}.*/ Place_t bn = b; VAR { do { SetOrg(bn,n); bn = NextF(bn); } while (bn != b); } SetOrgWall; Place_t an = a; { do { SetOrgWall(an); an = ONext(an); } while (an != a); } /* END SetOrgCycle */ Place_t Enext0(Place_t @p) { return a; } /* END Enext0 */ Place_t Enext1(Place_t @p) { return NextE(a); } /* END Enext1 */ Place_t NextE2(Place_t @p) { return NextE(NextE(a)); } /* END NextE2 */ Place_t ClockSpinEnext0(Place_t @p) { return Clock(Spin(Enext0(a))); } /* END ClockSpinEnext0 */ Place_t ClockSpinEnext1(Place_t @p) { return Clock(Spin(Enext1(a))); } /* END ClockSpinEnext1 */ Place_t ClockSpinNextE2(Place_t @p) { return Clock(Spin(NextE2(a))); } /* END ClockSpinNextE2 */ Place_t FnextEnext(Place_t @p) { return NextF(NextE(a)); } /* END FnextEnext */ Place_vec_t *Place_tsOnFrontier(Corner *co, uint cnum, uint order)== nc : REF Place_vec_t; { nc = Place_vec_new(order*order); if (cnum == 0) { if (order == 1) { nc[ 0] = Enext0(co.right[ 0]); } else if (order == 2){ nc[ 0] = Enext0(co.right[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.right[ 0]); /* */ nc[ 3] = Enext0(co.right[ 3]); } else if (order == 3){ nc[ 0] = Enext0(co.right[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.right[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext0(co.right[ 0]); /* */ nc[ 5] = Enext0(co.right[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext0(co.right[ 3]); /* */ nc[ 8] = Enext0(co.right[ 8]); } else if (order == 4){ nc[ 0] = Enext0(co.right[ 9]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.right[ 4]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.right[ 1]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.right[ 0]); /* */ nc[ 7] = Enext0(co.right[11]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext0(co.right[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.right[ 3]); /* */ nc[12] = Enext0(co.right[13]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext0(co.right[ 8]); /* */ nc[15] = Enext0(co.right[15]); } else if (order == 5){ nc[ 0] = Enext0(co.right[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext0(co.right[ 9]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.right[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.right[ 1]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext0(co.right[ 0]); /* */ nc[ 9] = Enext0(co.right[18]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.right[11]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext0(co.right[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext0(co.right[ 3]); /* */ nc[16] = Enext0(co.right[20]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext0(co.right[13]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext0(co.right[ 8]); /* */ nc[21] = Enext0(co.right[22]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext0(co.right[15]); /* */ nc[24] = Enext0(co.right[24]); } } if (cnum == 1) { if (order == 1) { nc[ 0] = Enext1(co.right[ 0]); } else if (order == 2){ nc[ 0] = Enext1(co.right[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.right[ 3]); /* */ nc[ 3] = Enext1(co.right[ 1]); } else if (order == 3){ nc[ 0] = Enext1(co.right[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.right[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext1(co.right[ 8]); /* */ nc[ 5] = Enext1(co.right[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext1(co.right[ 6]); /* */ nc[ 8] = Enext1(co.right[ 4]); } else if (order == 4){ nc[ 0] = Enext1(co.right[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.right[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.right[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.right[15]); /* */ nc[ 7] = Enext1(co.right[ 1]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext1(co.right[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.right[13]); /* */ nc[12] = Enext1(co.right[ 4]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext1(co.right[11]); /* */ nc[15] = Enext1(co.right[ 9]); } else if (order == 5){ nc[ 0] = Enext1(co.right[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.right[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.right[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.right[15]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext1(co.right[24]); /* */ nc[ 9] = Enext1(co.right[ 1]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.right[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext1(co.right[13]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext1(co.right[22]); /* */ nc[16] = Enext1(co.right[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext1(co.right[11]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext1(co.right[20]); /* */ nc[21] = Enext1(co.right[ 9]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext1(co.right[18]); /* */ nc[24] = Enext1(co.right[16]); } } if (cnum == 2) { if (order == 1) { nc[ 0] = NextE2(co.right[ 0]); } else if (order == 2){ nc[ 0] = NextE2(co.right[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.right[ 1]); /* */ nc[ 3] = NextE2(co.right[ 0]); } else if (order == 3){ nc[ 0] = NextE2(co.right[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.right[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = NextE2(co.right[ 4]); /* */ nc[ 5] = NextE2(co.right[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = NextE2(co.right[ 1]); /* */ nc[ 8] = NextE2(co.right[ 0]); } else if (order == 4){ nc[ 0] = NextE2(co.right[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.right[13]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.right[11]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.right[ 9]); /* */ nc[ 7] = NextE2(co.right[ 8]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = NextE2(co.right[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.right[ 4]); /* */ nc[12] = NextE2(co.right[ 3]); nc[13] = FnextEnext(nc[12]); nc[14] = NextE2(co.right[ 1]); /* */ nc[15] = NextE2(co.right[ 0]); } else if (order == 5){ nc[ 0] = NextE2(co.right[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.right[22]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.right[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.right[18]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = NextE2(co.right[16]); /* */ nc[ 9] = NextE2(co.right[15]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.right[13]); nc[12] = FnextEnext(nc[11]); nc[13] = NextE2(co.right[11]); nc[14] = FnextEnext(nc[13]); nc[15] = NextE2(co.right[ 9]); /* */ nc[16] = NextE2(co.right[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = NextE2(co.right[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = NextE2(co.right[ 4]); /* */ nc[21] = NextE2(co.right[ 3]); nc[22] = FnextEnext(nc[21]); nc[23] = NextE2(co.right[ 1]); /* */ nc[24] = NextE2(co.right[ 0]); } } if (cnum == 3) { if (order == 1) { nc[ 0] = Enext0(co.left[ 0]); } else if (order == 2){ nc[ 0] = Enext0(co.left[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.left[ 0]); /* */ nc[ 3] = Enext0(co.left[ 3]); } else if (order == 3){ nc[ 0] = Enext0(co.left[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.left[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext0(co.left[ 0]); /* */ nc[ 5] = Enext0(co.left[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext0(co.left[ 3]); /* */ nc[ 8] = Enext0(co.left[ 8]); } else if (order == 4){ nc[ 0] = Enext0(co.left[ 9]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext0(co.left[ 4]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.left[ 1]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.left[ 0]); /* */ nc[ 7] = Enext0(co.left[11]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext0(co.left[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.left[ 3]); /* */ nc[12] = Enext0(co.left[13]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext0(co.left[ 8]); /* */ nc[15] = Enext0(co.left[15]); } else if (order == 5){ nc[ 0] = Enext0(co.left[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext0(co.left[ 9]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.left[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.left[ 1]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext0(co.left[ 0]); /* */ nc[ 9] = Enext0(co.left[18]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.left[11]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext0(co.left[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext0(co.left[ 3]); /* */ nc[16] = Enext0(co.left[20]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext0(co.left[13]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext0(co.left[ 8]); /* */ nc[21] = Enext0(co.left[22]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext0(co.left[15]); /* */ nc[24] = Enext0(co.left[24]); } } if (cnum == 4) { if (order == 1) { nc[ 0] = Enext1(co.left[ 0]); } else if (order == 2){ nc[ 0] = Enext1(co.left[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.left[ 3]); /* */ nc[ 3] = Enext1(co.left[ 1]); } else if (order == 3){ nc[ 0] = Enext1(co.left[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.left[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext1(co.left[ 8]); /* */ nc[ 5] = Enext1(co.left[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext1(co.left[ 6]); /* */ nc[ 8] = Enext1(co.left[ 4]); } else if (order == 4){ nc[ 0] = Enext1(co.left[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.left[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.left[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.left[15]); /* */ nc[ 7] = Enext1(co.left[ 1]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext1(co.left[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.left[13]); /* */ nc[12] = Enext1(co.left[ 4]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext1(co.left[11]); /* */ nc[15] = Enext1(co.left[ 9]); } else if (order == 5){ nc[ 0] = Enext1(co.left[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.left[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.left[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.left[15]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext1(co.left[24]); /* */ nc[ 9] = Enext1(co.left[ 1]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.left[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext1(co.left[13]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext1(co.left[22]); /* */ nc[16] = Enext1(co.left[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext1(co.left[11]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext1(co.left[20]); /* */ nc[21] = Enext1(co.left[ 9]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext1(co.left[18]); /* */ nc[24] = Enext1(co.left[16]); } } if (cnum == 5) { if (order == 1) { nc[ 0] = NextE2(co.left[ 0]); } else if (order == 2){ nc[ 0] = NextE2(co.left[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.left[ 1]); /* */ nc[ 3] = NextE2(co.left[ 0]); } else if (order == 3){ nc[ 0] = NextE2(co.left[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.left[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = NextE2(co.left[ 4]); /* */ nc[ 5] = NextE2(co.left[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = NextE2(co.left[ 1]); /* */ nc[ 8] = NextE2(co.left[ 0]); } else if (order == 4){ nc[ 0] = NextE2(co.left[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.left[13]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.left[11]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.left[ 9]); /* */ nc[ 7] = NextE2(co.left[ 8]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = NextE2(co.left[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.left[ 4]); /* */ nc[12] = NextE2(co.left[ 3]); nc[13] = FnextEnext(nc[12]); nc[14] = NextE2(co.left[ 1]); /* */ nc[15] = NextE2(co.left[ 0]); } else if (order == 5){ nc[ 0] = NextE2(co.left[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.left[22]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.left[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.left[18]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = NextE2(co.left[16]); /* */ nc[ 9] = NextE2(co.left[15]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.left[13]); nc[12] = FnextEnext(nc[11]); nc[13] = NextE2(co.left[11]); nc[14] = FnextEnext(nc[13]); nc[15] = NextE2(co.left[ 9]); /* */ nc[16] = NextE2(co.left[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = NextE2(co.left[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = NextE2(co.left[ 4]); /* */ nc[21] = NextE2(co.left[ 3]); nc[22] = FnextEnext(nc[21]); nc[23] = NextE2(co.left[ 1]); /* */ nc[24] = NextE2(co.left[ 0]); } } if (cnum == 6) { if (order == 1) { nc[ 0] = ClockSpinEnext1(co.front[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext1(co.front[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.front[ 3]); /* */ nc[ 3] = ClockSpinEnext1(co.front[ 1]); } else if (order == 3){ nc[ 0] = ClockSpinEnext1(co.front[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.front[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext1(co.front[ 8]); /* */ nc[ 5] = ClockSpinEnext1(co.front[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext1(co.front[ 6]); /* */ nc[ 8] = ClockSpinEnext1(co.front[ 4]); } else if (order == 4){ nc[ 0] = ClockSpinEnext1(co.front[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.front[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.front[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.front[15]); /* */ nc[ 7] = ClockSpinEnext1(co.front[ 1]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext1(co.front[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.front[13]); /* */ nc[12] = ClockSpinEnext1(co.front[ 4]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext1(co.front[11]); /* */ nc[15] = ClockSpinEnext1(co.front[ 9]); } else if (order == 5){ nc[ 0] = ClockSpinEnext1(co.front[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.front[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.front[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.front[15]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext1(co.front[24]); /* */ nc[ 9] = ClockSpinEnext1(co.front[ 1]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.front[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext1(co.front[13]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext1(co.front[22]); /* */ nc[16] = ClockSpinEnext1(co.front[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext1(co.front[11]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext1(co.front[20]); /* */ nc[21] = ClockSpinEnext1(co.front[ 9]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext1(co.front[18]); /* */ nc[24] = ClockSpinEnext1(co.front[16]); } } if (cnum == 7) { if (order == 1) { nc[ 0] = ClockSpinEnext0(co.front[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext0(co.front[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.front[ 1]); /* */ nc[ 3] = ClockSpinEnext0(co.front[ 0]); } else if (order == 3){ nc[ 0] = ClockSpinEnext0(co.front[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.front[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext0(co.front[ 4]); /* */ nc[ 5] = ClockSpinEnext0(co.front[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext0(co.front[ 1]); /* */ nc[ 8] = ClockSpinEnext0(co.front[ 0]); } else if (order == 4){ nc[ 0] = ClockSpinEnext0(co.front[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.front[13]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.front[11]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.front[ 9]); /* */ nc[ 7] = ClockSpinEnext0(co.front[ 8]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext0(co.front[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.front[ 4]); /* */ nc[12] = ClockSpinEnext0(co.front[ 3]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext0(co.front[ 1]); /* */ nc[15] = ClockSpinEnext0(co.front[ 0]); } else if (order == 5){ nc[ 0] = ClockSpinEnext0(co.front[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.front[22]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.front[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.front[18]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext0(co.front[16]); /* */ nc[ 9] = ClockSpinEnext0(co.front[15]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.front[13]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext0(co.front[11]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext0(co.front[ 9]); /* */ nc[16] = ClockSpinEnext0(co.front[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext0(co.front[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext0(co.front[ 4]); /* */ nc[21] = ClockSpinEnext0(co.front[ 3]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext0(co.front[ 1]); /* */ nc[24] = ClockSpinEnext0(co.front[ 0]); } } if (cnum == 8) { if (order == 1) { nc[ 0] = ClockSpinNextE2(co.front[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinNextE2(co.front[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.front[ 0]); /* */ nc[ 3] = ClockSpinNextE2(co.front[ 3]); } else if (order == 3){ nc[ 0] = ClockSpinNextE2(co.front[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.front[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinNextE2(co.front[ 0]); /* */ nc[ 5] = ClockSpinNextE2(co.front[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinNextE2(co.front[ 3]); /* */ nc[ 8] = ClockSpinNextE2(co.front[ 8]); } else if (order == 4){ nc[ 0] = ClockSpinNextE2(co.front[ 9]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.front[ 4]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.front[ 1]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.front[ 0]); /* */ nc[ 7] = ClockSpinNextE2(co.front[11]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinNextE2(co.front[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.front[ 3]); /* */ nc[12] = ClockSpinNextE2(co.front[13]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinNextE2(co.front[ 8]); /* */ nc[15] = ClockSpinNextE2(co.front[15]); } else if (order == 5){ nc[ 0] = ClockSpinNextE2(co.front[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.front[ 9]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.front[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.front[ 1]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinNextE2(co.front[ 0]); /* */ nc[ 9] = ClockSpinNextE2(co.front[18]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.front[11]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinNextE2(co.front[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinNextE2(co.front[ 3]); /* */ nc[16] = ClockSpinNextE2(co.front[20]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinNextE2(co.front[13]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinNextE2(co.front[ 8]); /* */ nc[21] = ClockSpinNextE2(co.front[22]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinNextE2(co.front[15]); /* */ nc[24] = ClockSpinNextE2(co.front[24]); } } if (cnum == 9) { if (order == 1) { nc[ 0] = Enext1(co.back[ 0]); } else if (order == 2){ nc[ 0] = Enext1(co.back[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.back[ 0]); /* */ nc[ 3] = Enext1(co.back[ 1]); } else if (order == 3){ nc[ 0] = Enext1(co.back[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.back[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext1(co.back[ 0]); /* */ nc[ 5] = Enext1(co.back[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext1(co.back[ 1]); /* */ nc[ 8] = Enext1(co.back[ 4]); } else if (order == 4){ nc[ 0] = Enext1(co.back[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.back[ 8]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.back[ 3]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.back[ 0]); /* */ nc[ 7] = Enext1(co.back[13]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext1(co.back[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.back[ 1]); /* */ nc[12] = Enext1(co.back[11]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext1(co.back[ 4]); /* */ nc[15] = Enext1(co.back[ 9]); } else if (order == 5){ nc[ 0] = Enext1(co.back[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.back[15]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.back[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.back[ 3]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext1(co.back[ 0]); /* */ nc[ 9] = Enext1(co.back[22]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.back[13]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext1(co.back[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext1(co.back[ 1]); /* */ nc[16] = Enext1(co.back[20]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext1(co.back[11]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext1(co.back[ 4]); /* */ nc[21] = Enext1(co.back[18]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext1(co.back[ 9]); /* */ nc[24] = Enext1(co.back[16]); } } if (cnum == 10) { if (order == 1) { nc[ 0] = NextE2(co.back[ 0]); } else if (order == 2){ nc[ 0] = NextE2(co.back[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.back[ 1]); /* */ nc[ 3] = NextE2(co.back[ 3]); } else if (order == 3){ nc[ 0] = NextE2(co.back[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.back[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = NextE2(co.back[ 4]); /* */ nc[ 5] = NextE2(co.back[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = NextE2(co.back[ 6]); /* */ nc[ 8] = NextE2(co.back[ 8]); } else if (order == 4){ nc[ 0] = NextE2(co.back[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.back[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.back[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.back[ 9]); /* */ nc[ 7] = NextE2(co.back[ 3]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = NextE2(co.back[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.back[11]); /* */ nc[12] = NextE2(co.back[ 8]); nc[13] = FnextEnext(nc[12]); nc[14] = NextE2(co.back[13]); /* */ nc[15] = NextE2(co.back[15]); } else if (order == 5){ nc[ 0] = NextE2(co.back[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.back[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.back[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.back[ 9]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = NextE2(co.back[16]); /* */ nc[ 9] = NextE2(co.back[ 3]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.back[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = NextE2(co.back[11]); nc[14] = FnextEnext(nc[13]); nc[15] = NextE2(co.back[18]); /* */ nc[16] = NextE2(co.back[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = NextE2(co.back[13]); nc[19] = FnextEnext(nc[18]); nc[20] = NextE2(co.back[20]); /* */ nc[21] = NextE2(co.back[15]); nc[22] = FnextEnext(nc[21]); nc[23] = NextE2(co.back[22]); /* */ nc[24] = NextE2(co.back[24]); } } if (cnum == 11) { if (order == 1) { nc[ 0] = Enext0(co.back[ 0]); } else if (order == 2){ nc[ 0] = Enext0(co.back[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.back[ 3]); /* */ nc[ 3] = Enext0(co.back[ 0]); } else if (order == 3){ nc[ 0] = Enext0(co.back[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.back[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext0(co.back[ 8]); /* */ nc[ 5] = Enext0(co.back[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext0(co.back[ 3]); /* */ nc[ 8] = Enext0(co.back[ 0]); } else if (order == 4){ nc[ 0] = Enext0(co.back[ 9]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext0(co.back[11]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.back[13]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.back[15]); /* */ nc[ 7] = Enext0(co.back[ 4]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext0(co.back[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.back[ 8]); /* */ nc[12] = Enext0(co.back[ 1]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext0(co.back[ 3]); /* */ nc[15] = Enext0(co.back[ 0]); } else if (order == 5){ nc[ 0] = Enext0(co.back[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext0(co.back[18]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.back[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.back[22]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext0(co.back[24]); /* */ nc[ 9] = Enext0(co.back[ 9]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.back[11]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext0(co.back[13]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext0(co.back[15]); /* */ nc[16] = Enext0(co.back[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext0(co.back[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext0(co.back[ 8]); /* */ nc[21] = Enext0(co.back[ 1]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext0(co.back[ 3]); /* */ nc[24] = Enext0(co.back[ 0]); } } if (cnum == 12) { if (order == 1) { nc[ 0] = ClockSpinEnext0(co.right[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext0(co.right[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.right[ 1]); /* */ nc[ 3] = ClockSpinEnext0(co.right[ 3]); } else if (order == 3){ nc[ 0] = ClockSpinEnext0(co.right[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.right[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext0(co.right[ 4]); /* */ nc[ 5] = ClockSpinEnext0(co.right[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext0(co.right[ 6]); /* */ nc[ 8] = ClockSpinEnext0(co.right[ 8]); } else if (order == 4){ nc[ 0] = ClockSpinEnext0(co.right[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.right[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.right[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.right[ 9]); /* */ nc[ 7] = ClockSpinEnext0(co.right[ 3]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext0(co.right[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.right[11]); /* */ nc[12] = ClockSpinEnext0(co.right[ 8]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext0(co.right[13]); /* */ nc[15] = ClockSpinEnext0(co.right[15]); } else if (order == 5){ nc[ 0] = ClockSpinEnext0(co.right[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.right[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.right[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.right[ 9]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext0(co.right[16]); /* */ nc[ 9] = ClockSpinEnext0(co.right[ 3]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.right[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext0(co.right[11]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext0(co.right[18]); /* */ nc[16] = ClockSpinEnext0(co.right[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext0(co.right[13]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext0(co.right[20]); /* */ nc[21] = ClockSpinEnext0(co.right[15]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext0(co.right[22]); /* */ nc[24] = ClockSpinEnext0(co.right[24]); } } if (cnum == 13) { if (order == 1) { nc[ 0] = ClockSpinEnext1(co.right[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext1(co.right[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.right[ 0]); /* */ nc[ 3] = ClockSpinEnext1(co.right[ 1]); } else if (order == 3){ nc[ 0] = ClockSpinEnext1(co.right[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.right[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext1(co.right[ 0]); /* */ nc[ 5] = ClockSpinEnext1(co.right[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext1(co.right[ 1]); /* */ nc[ 8] = ClockSpinEnext1(co.right[ 4]); } else if (order == 4){ nc[ 0] = ClockSpinEnext1(co.right[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.right[ 8]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.right[ 3]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.right[ 0]); /* */ nc[ 7] = ClockSpinEnext1(co.right[13]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext1(co.right[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.right[ 1]); /* */ nc[12] = ClockSpinEnext1(co.right[11]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext1(co.right[ 4]); /* */ nc[15] = ClockSpinEnext1(co.right[ 9]); } else if (order == 5){ nc[ 0] = ClockSpinEnext1(co.right[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.right[15]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.right[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.right[ 3]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext1(co.right[ 0]); /* */ nc[ 9] = ClockSpinEnext1(co.right[22]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.right[13]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext1(co.right[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext1(co.right[ 1]); /* */ nc[16] = ClockSpinEnext1(co.right[20]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext1(co.right[11]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext1(co.right[ 4]); /* */ nc[21] = ClockSpinEnext1(co.right[18]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext1(co.right[ 9]); /* */ nc[24] = ClockSpinEnext1(co.right[16]); } } if (cnum == 14) { if (order == 1) { nc[ 0] = ClockSpinNextE2(co.right[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinNextE2(co.right[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.right[ 3]); /* */ nc[ 3] = ClockSpinNextE2(co.right[ 0]); } else if (order == 3){ nc[ 0] = ClockSpinNextE2(co.right[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.right[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinNextE2(co.right[ 8]); /* */ nc[ 5] = ClockSpinNextE2(co.right[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinNextE2(co.right[ 3]); /* */ nc[ 8] = ClockSpinNextE2(co.right[ 0]); } else if (order == 4){ nc[ 0] = ClockSpinNextE2(co.right[ 9]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.right[11]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.right[13]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.right[15]); /* */ nc[ 7] = ClockSpinNextE2(co.right[ 4]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinNextE2(co.right[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.right[ 8]); /* */ nc[12] = ClockSpinNextE2(co.right[ 1]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinNextE2(co.right[ 3]); /* */ nc[15] = ClockSpinNextE2(co.right[ 0]); } else if (order == 5){ nc[ 0] = ClockSpinNextE2(co.right[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.right[18]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.right[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.right[22]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinNextE2(co.right[24]); /* */ nc[ 9] = ClockSpinNextE2(co.right[ 9]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.right[11]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinNextE2(co.right[13]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinNextE2(co.right[15]); /* */ nc[16] = ClockSpinNextE2(co.right[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinNextE2(co.right[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinNextE2(co.right[ 8]); /* */ nc[21] = ClockSpinNextE2(co.right[ 1]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinNextE2(co.right[ 3]); /* */ nc[24] = ClockSpinNextE2(co.right[ 0]); } } if (cnum == 15) { if (order == 1) { nc[ 0] = ClockSpinEnext0(co.left[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext0(co.left[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.left[ 1]); /* */ nc[ 3] = ClockSpinEnext0(co.left[ 3]); } else if (order == 3){ nc[ 0] = ClockSpinEnext0(co.left[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.left[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext0(co.left[ 4]); /* */ nc[ 5] = ClockSpinEnext0(co.left[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext0(co.left[ 6]); /* */ nc[ 8] = ClockSpinEnext0(co.left[ 8]); } else if (order == 4){ nc[ 0] = ClockSpinEnext0(co.left[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.left[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.left[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.left[ 9]); /* */ nc[ 7] = ClockSpinEnext0(co.left[ 3]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext0(co.left[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.left[11]); /* */ nc[12] = ClockSpinEnext0(co.left[ 8]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext0(co.left[13]); /* */ nc[15] = ClockSpinEnext0(co.left[15]); } else if (order == 5){ nc[ 0] = ClockSpinEnext0(co.left[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.left[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.left[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.left[ 9]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext0(co.left[16]); /* */ nc[ 9] = ClockSpinEnext0(co.left[ 3]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.left[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext0(co.left[11]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext0(co.left[18]); /* */ nc[16] = ClockSpinEnext0(co.left[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext0(co.left[13]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext0(co.left[20]); /* */ nc[21] = ClockSpinEnext0(co.left[15]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext0(co.left[22]); /* */ nc[24] = ClockSpinEnext0(co.left[24]); } } if (cnum == 16) { if (order == 1) { nc[ 0] = ClockSpinEnext1(co.left[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext1(co.left[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.left[ 0]); /* */ nc[ 3] = ClockSpinEnext1(co.left[ 1]); } else if (order == 3){ nc[ 0] = ClockSpinEnext1(co.left[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.left[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext1(co.left[ 0]); /* */ nc[ 5] = ClockSpinEnext1(co.left[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext1(co.left[ 1]); /* */ nc[ 8] = ClockSpinEnext1(co.left[ 4]); } else if (order == 4){ nc[ 0] = ClockSpinEnext1(co.left[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.left[ 8]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.left[ 3]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.left[ 0]); /* */ nc[ 7] = ClockSpinEnext1(co.left[13]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext1(co.left[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.left[ 1]); /* */ nc[12] = ClockSpinEnext1(co.left[11]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext1(co.left[ 4]); /* */ nc[15] = ClockSpinEnext1(co.left[ 9]); } else if (order == 5){ nc[ 0] = ClockSpinEnext1(co.left[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.left[15]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.left[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.left[ 3]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext1(co.left[ 0]); /* */ nc[ 9] = ClockSpinEnext1(co.left[22]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.left[13]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext1(co.left[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext1(co.left[ 1]); /* */ nc[16] = ClockSpinEnext1(co.left[20]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext1(co.left[11]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext1(co.left[ 4]); /* */ nc[21] = ClockSpinEnext1(co.left[18]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext1(co.left[ 9]); /* */ nc[24] = ClockSpinEnext1(co.left[16]); } } if (cnum == 17) { if (order == 1) { nc[ 0] = ClockSpinNextE2(co.left[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinNextE2(co.left[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.left[ 3]); /* */ nc[ 3] = ClockSpinNextE2(co.left[ 0]); } else if (order == 3){ nc[ 0] = ClockSpinNextE2(co.left[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.left[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinNextE2(co.left[ 8]); /* */ nc[ 5] = ClockSpinNextE2(co.left[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinNextE2(co.left[ 3]); /* */ nc[ 8] = ClockSpinNextE2(co.left[ 0]); } else if (order == 4){ nc[ 0] = ClockSpinNextE2(co.left[ 9]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.left[11]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.left[13]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.left[15]); /* */ nc[ 7] = ClockSpinNextE2(co.left[ 4]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinNextE2(co.left[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.left[ 8]); /* */ nc[12] = ClockSpinNextE2(co.left[ 1]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinNextE2(co.left[ 3]); /* */ nc[15] = ClockSpinNextE2(co.left[ 0]); } else if (order == 5){ nc[ 0] = ClockSpinNextE2(co.left[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.left[18]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.left[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.left[22]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinNextE2(co.left[24]); /* */ nc[ 9] = ClockSpinNextE2(co.left[ 9]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.left[11]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinNextE2(co.left[13]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinNextE2(co.left[15]); /* */ nc[16] = ClockSpinNextE2(co.left[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinNextE2(co.left[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinNextE2(co.left[ 8]); /* */ nc[21] = ClockSpinNextE2(co.left[ 1]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinNextE2(co.left[ 3]); /* */ nc[24] = ClockSpinNextE2(co.left[ 0]); } } if (cnum == 18) { if (order == 1) { nc[ 0] = Enext1(co.front[ 0]); } else if (order == 2){ nc[ 0] = Enext1(co.front[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.front[ 0]); /* */ nc[ 3] = Enext1(co.front[ 1]); } else if (order == 3){ nc[ 0] = Enext1(co.front[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext1(co.front[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext1(co.front[ 0]); /* */ nc[ 5] = Enext1(co.front[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext1(co.front[ 1]); /* */ nc[ 8] = Enext1(co.front[ 4]); } else if (order == 4){ nc[ 0] = Enext1(co.front[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.front[ 8]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.front[ 3]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.front[ 0]); /* */ nc[ 7] = Enext1(co.front[13]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext1(co.front[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.front[ 1]); /* */ nc[12] = Enext1(co.front[11]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext1(co.front[ 4]); /* */ nc[15] = Enext1(co.front[ 9]); } else if (order == 5){ nc[ 0] = Enext1(co.front[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext1(co.front[15]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext1(co.front[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext1(co.front[ 3]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext1(co.front[ 0]); /* */ nc[ 9] = Enext1(co.front[22]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext1(co.front[13]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext1(co.front[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext1(co.front[ 1]); /* */ nc[16] = Enext1(co.front[20]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext1(co.front[11]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext1(co.front[ 4]); /* */ nc[21] = Enext1(co.front[18]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext1(co.front[ 9]); /* */ nc[24] = Enext1(co.front[16]); } } if (cnum == 19) { if (order == 1) { nc[ 0] = Enext0(co.front[ 0]); } else if (order == 2){ nc[ 0] = Enext0(co.front[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.front[ 3]); /* */ nc[ 3] = Enext0(co.front[ 0]); } else if (order == 3){ nc[ 0] = Enext0(co.front[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = Enext0(co.front[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = Enext0(co.front[ 8]); /* */ nc[ 5] = Enext0(co.front[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = Enext0(co.front[ 3]); /* */ nc[ 8] = Enext0(co.front[ 0]); } else if (order == 4){ nc[ 0] = Enext0(co.front[ 9]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext0(co.front[11]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.front[13]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.front[15]); /* */ nc[ 7] = Enext0(co.front[ 4]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = Enext0(co.front[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.front[ 8]); /* */ nc[12] = Enext0(co.front[ 1]); nc[13] = FnextEnext(nc[12]); nc[14] = Enext0(co.front[ 3]); /* */ nc[15] = Enext0(co.front[ 0]); } else if (order == 5){ nc[ 0] = Enext0(co.front[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = Enext0(co.front[18]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = Enext0(co.front[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = Enext0(co.front[22]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = Enext0(co.front[24]); /* */ nc[ 9] = Enext0(co.front[ 9]); nc[10] = FnextEnext(nc[ 9]); nc[11] = Enext0(co.front[11]); nc[12] = FnextEnext(nc[11]); nc[13] = Enext0(co.front[13]); nc[14] = FnextEnext(nc[13]); nc[15] = Enext0(co.front[15]); /* */ nc[16] = Enext0(co.front[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = Enext0(co.front[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = Enext0(co.front[ 8]); /* */ nc[21] = Enext0(co.front[ 1]); nc[22] = FnextEnext(nc[21]); nc[23] = Enext0(co.front[ 3]); /* */ nc[24] = Enext0(co.front[ 0]); } } if (cnum == 20) { if (order == 1) { nc[ 0] = NextE2(co.front[ 0]); } else if (order == 2){ nc[ 0] = NextE2(co.front[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.front[ 1]); /* */ nc[ 3] = NextE2(co.front[ 3]); } else if (order == 3){ nc[ 0] = NextE2(co.front[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = NextE2(co.front[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = NextE2(co.front[ 4]); /* */ nc[ 5] = NextE2(co.front[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = NextE2(co.front[ 6]); /* */ nc[ 8] = NextE2(co.front[ 8]); } else if (order == 4){ nc[ 0] = NextE2(co.front[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.front[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.front[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.front[ 9]); /* */ nc[ 7] = NextE2(co.front[ 3]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = NextE2(co.front[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.front[11]); /* */ nc[12] = NextE2(co.front[ 8]); nc[13] = FnextEnext(nc[12]); nc[14] = NextE2(co.front[13]); /* */ nc[15] = NextE2(co.front[15]); } else if (order == 5){ nc[ 0] = NextE2(co.front[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = NextE2(co.front[ 1]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = NextE2(co.front[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = NextE2(co.front[ 9]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = NextE2(co.front[16]); /* */ nc[ 9] = NextE2(co.front[ 3]); nc[10] = FnextEnext(nc[ 9]); nc[11] = NextE2(co.front[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = NextE2(co.front[11]); nc[14] = FnextEnext(nc[13]); nc[15] = NextE2(co.front[18]); /* */ nc[16] = NextE2(co.front[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = NextE2(co.front[13]); nc[19] = FnextEnext(nc[18]); nc[20] = NextE2(co.front[20]); /* */ nc[21] = NextE2(co.front[15]); nc[22] = FnextEnext(nc[21]); nc[23] = NextE2(co.front[22]); /* */ nc[24] = NextE2(co.front[24]); } } if (cnum == 21) { if (order == 1) { nc[ 0] = ClockSpinEnext1(co.back[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext1(co.back[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.back[ 3]); /* */ nc[ 3] = ClockSpinEnext1(co.back[ 1]); } else if (order == 3){ nc[ 0] = ClockSpinEnext1(co.back[ 0]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext1(co.back[ 3]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext1(co.back[ 8]); /* */ nc[ 5] = ClockSpinEnext1(co.back[ 1]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext1(co.back[ 6]); /* */ nc[ 8] = ClockSpinEnext1(co.back[ 4]); } else if (order == 4){ nc[ 0] = ClockSpinEnext1(co.back[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.back[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.back[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.back[15]); /* */ nc[ 7] = ClockSpinEnext1(co.back[ 1]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext1(co.back[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.back[13]); /* */ nc[12] = ClockSpinEnext1(co.back[ 4]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext1(co.back[11]); /* */ nc[15] = ClockSpinEnext1(co.back[ 9]); } else if (order == 5){ nc[ 0] = ClockSpinEnext1(co.back[ 0]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext1(co.back[ 3]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext1(co.back[ 8]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext1(co.back[15]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext1(co.back[24]); /* */ nc[ 9] = ClockSpinEnext1(co.back[ 1]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext1(co.back[ 6]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext1(co.back[13]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext1(co.back[22]); /* */ nc[16] = ClockSpinEnext1(co.back[ 4]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext1(co.back[11]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext1(co.back[20]); /* */ nc[21] = ClockSpinEnext1(co.back[ 9]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext1(co.back[18]); /* */ nc[24] = ClockSpinEnext1(co.back[16]); } } if (cnum == 22) { if (order == 1) { nc[ 0] = ClockSpinNextE2(co.back[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinNextE2(co.back[ 1]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.back[ 0]); /* */ nc[ 3] = ClockSpinNextE2(co.back[ 3]); } else if (order == 3){ nc[ 0] = ClockSpinNextE2(co.back[ 4]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinNextE2(co.back[ 1]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinNextE2(co.back[ 0]); /* */ nc[ 5] = ClockSpinNextE2(co.back[ 6]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinNextE2(co.back[ 3]); /* */ nc[ 8] = ClockSpinNextE2(co.back[ 8]); } else if (order == 4){ nc[ 0] = ClockSpinNextE2(co.back[ 9]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.back[ 4]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.back[ 1]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.back[ 0]); /* */ nc[ 7] = ClockSpinNextE2(co.back[11]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinNextE2(co.back[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.back[ 3]); /* */ nc[12] = ClockSpinNextE2(co.back[13]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinNextE2(co.back[ 8]); /* */ nc[15] = ClockSpinNextE2(co.back[15]); } else if (order == 5){ nc[ 0] = ClockSpinNextE2(co.back[16]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinNextE2(co.back[ 9]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinNextE2(co.back[ 4]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinNextE2(co.back[ 1]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinNextE2(co.back[ 0]); /* */ nc[ 9] = ClockSpinNextE2(co.back[18]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinNextE2(co.back[11]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinNextE2(co.back[ 6]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinNextE2(co.back[ 3]); /* */ nc[16] = ClockSpinNextE2(co.back[20]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinNextE2(co.back[13]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinNextE2(co.back[ 8]); /* */ nc[21] = ClockSpinNextE2(co.back[22]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinNextE2(co.back[15]); /* */ nc[24] = ClockSpinNextE2(co.back[24]); } } if (cnum == 23) { if (order == 1) { nc[ 0] = ClockSpinEnext0(co.back[ 0]); } else if (order == 2){ nc[ 0] = ClockSpinEnext0(co.back[ 3]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.back[ 1]); /* */ nc[ 3] = ClockSpinEnext0(co.back[ 0]); } else if (order == 3){ nc[ 0] = ClockSpinEnext0(co.back[ 8]); nc[ 1] = FnextEnext(nc[0]); nc[ 2] = ClockSpinEnext0(co.back[ 6]); nc[ 3] = FnextEnext(nc[2]); nc[ 4] = ClockSpinEnext0(co.back[ 4]); /* */ nc[ 5] = ClockSpinEnext0(co.back[ 3]); nc[ 6] = FnextEnext(nc[5]); nc[ 7] = ClockSpinEnext0(co.back[ 1]); /* */ nc[ 8] = ClockSpinEnext0(co.back[ 0]); } else if (order == 4){ nc[ 0] = ClockSpinEnext0(co.back[15]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.back[13]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.back[11]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.back[ 9]); /* */ nc[ 7] = ClockSpinEnext0(co.back[ 8]); nc[ 8] = FnextEnext(nc[ 7]); nc[ 9] = ClockSpinEnext0(co.back[ 6]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.back[ 4]); /* */ nc[12] = ClockSpinEnext0(co.back[ 3]); nc[13] = FnextEnext(nc[12]); nc[14] = ClockSpinEnext0(co.back[ 1]); /* */ nc[15] = ClockSpinEnext0(co.back[ 0]); } else if (order == 5){ nc[ 0] = ClockSpinEnext0(co.back[24]); nc[ 1] = FnextEnext(nc[ 0]); nc[ 2] = ClockSpinEnext0(co.back[22]); nc[ 3] = FnextEnext(nc[ 2]); nc[ 4] = ClockSpinEnext0(co.back[20]); nc[ 5] = FnextEnext(nc[ 4]); nc[ 6] = ClockSpinEnext0(co.back[18]); nc[ 7] = FnextEnext(nc[ 6]); nc[ 8] = ClockSpinEnext0(co.back[16]); /* */ nc[ 9] = ClockSpinEnext0(co.back[15]); nc[10] = FnextEnext(nc[ 9]); nc[11] = ClockSpinEnext0(co.back[13]); nc[12] = FnextEnext(nc[11]); nc[13] = ClockSpinEnext0(co.back[11]); nc[14] = FnextEnext(nc[13]); nc[15] = ClockSpinEnext0(co.back[ 9]); /* */ nc[16] = ClockSpinEnext0(co.back[ 8]); nc[17] = FnextEnext(nc[16]); nc[18] = ClockSpinEnext0(co.back[ 6]); nc[19] = FnextEnext(nc[18]); nc[20] = ClockSpinEnext0(co.back[ 4]); /* */ nc[21] = ClockSpinEnext0(co.back[ 3]); nc[22] = FnextEnext(nc[21]); nc[23] = ClockSpinEnext0(co.back[ 1]); /* */ nc[24] = ClockSpinEnext0(co.back[ 0]); } } return nc; } /* END Place_tsOnFrontier */ { } Refine. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/CmpAreaEnergy.c /* See {CmpAreaEnergy.h} */ // #INCLUDE #include // #INCLUDE #include struct CmpAreaEnergy_private_t { double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements */ bool_vec_t vVar; /* TRUE if node is variable */ bool_vec_t wallRelevant; /* TRUE if wall is relevant */ double_vec_t af; /* Area of each wall relevant */ double_vec_t eDaf; /* (Work) Derivative of Energy rel. to wall area */ }; SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0/((double)top->wall.ne); erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->wallRelevant = bool_vec_new(top->wall.ne); /* Allocate area tables: */ erg->af = double_vec_new(top->wall.ne); erg->eDaf = double_vec_new(top->wall.ne); /* Just in case the client forgets to call {defVar}: */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->wall.ne; i++){ erg->wallRelevant.e[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which wall are relevant to Area Compression energy. A wall is relevant iff it exists, and the wall have at least one variable corner. */ int NV = erg->top->node.ne; int NF = erg->top->wall.ne; bool_vec_t vVar = erg->vVar^; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; { assert(variable.ne == NV); vVar = variable; /* Find the relevant walls: */ for (i = 0; i < NF; i++){ wallRelevant.e[i] = FALSE; } for (i = 0; i < NF; i++) { ??? f = wall[i]; ??? a = f.pa^; Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); Node_t w = OrgV(PrevE(a)); bool_t vvar = (vVar.e[u->num]) || (vVar.e[v->num]) || (vVar.e[w->num]); { if ((f->exists) && (vvar)) { assert(u->exists) && (v->exists) && (w->exists); wallRelevant.e[i] = TRUE; } else { wallRelevant.e[i] = FALSE; } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; int NF = erg->top->wall.ne; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; ??? af = erg->af^; ??? eDaf = erg->eDaf^; ??? vVar = erg->vVar^; ??? K = erg->K; ??? A = ((double)erg->area); { void Accum_a(*u,v,w: uint; VAR area: double) /* Compute the area of triangle with endpoints nodes (number) u,v,w. */ { ??? aa = r4_Sub(c[u], c[v]); ??? a = r4_Norm(aa); ??? bb = r4_Sub(c[u], c[w]); ??? b = r4_Norm(bb); ??? cc = r4_Sub(c[v],c[w]); ??? c = r4_Norm(cc); ??? p = (a+b+c); ??? p2a = p - 2.0 * a; ??? p2b = p - 2.0 * b; ??? p2c = p - 2.0 * c; double num == sqrt(p * p2a * p2b * p2c); { assert(p!=0.0); area = num/4.0; } } Accum_a; void Accum_e_from_a(a: double; double e; VAR VAR etDa : double) /* Adds to {e} the energy term corresponting to area wall {a} . */ { ??? r = a/A; ??? s = Math.log(r)*Math.log(r); { assert(a!=0.0); assert(r!=0.0); assert(0.0 <= s); e = e + K * s; if (grad) { etDa = 2.0 * K * Math.log(r)/a; } else { etDa = 0.0; } } } Accum_e_from_a; void Distribute_eDa(iu, iv, iw: uint; eDa: double) /* Accumulates in {eDc} the gradient of {e} relative to the corners of the triangle {iu iv iw}, given the derivative {eDa} of {e} relative to the triangle's area {a}. */ { ??? u = c[iu]; ??? v = c[iv]; ??? w = c[iw]; ??? aa = r4_Sub(u,v); ??? a = r4_Norm(aa); ??? bb = r4_Sub(u,w); ??? b = r4_Norm(bb); ??? cc = r4_Sub(v,w); ??? c = r4_Norm(cc); ??? abc = a * b * c; ??? bc = abc/a; ??? ac = abc/b; ??? ab = abc/c; ??? p = (a+b+c); ??? p2a = p - 2.0 * a; ??? p2b = p - 2.0 * b; ??? p2c = p - 2.0 * c; ??? num = sqrt(p * p2a * p2b * p2c); ??? eDv = eDc[iv]; ??? eDu = eDc[iu]; ??? eDw == eDc[iw]; { if (p!=0.0) { ??? p3 = p * p * p; ??? p2 = p * p; ??? num1 = 4.0*p3-6.0*p2*(p)+8.0*p*(bc+ac+ab)-8.0*abc; ??? aDp = (1.0/8.0) * num1 * (1.0/num); ??? eDp = eDa * aDp; ??? pDcu = r4_Mix(1.0/a,aa,1.0/b,bb); ??? pDcv = r4_Mix(-1.0/a,aa,1.0/c,cc); ??? pDcw = r4_Mix(-1.0/b,bb,-1.0/c,cc); ??? eDcu = r4_Scale(eDp, pDcu); ??? eDcv = r4_Scale(eDp, pDcv); ??? eDcw = r4_Scale(eDp, pDcw); { if (vVar.e[iv]) { eDv = r4_Add(eDv,eDcv); } if (vVar.e[iu]) { eDu = r4_Add(eDu, eDcu); } if (vVar.e[iw]) { eDw = r4_Add(eDw, eDcw); } } } } } Distribute_eDa; { /* Clear area accumulators: */ for (i = 0; i < NF; i++){ af[i] = 0.0; } /* Enumerate walls and accumulate wall areas: */ for (j = 0; j < NF; j++) { if (wallRelevant.e[j]) { ??? f = wall[j]; ??? a = f.pa^; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; { Accum_a(un,vn,wn,af[j]); } } } /* Compute energy {e} from walls areas, and the gradient {eDaf} */ e = 0.0; for (j = 0; j < NF; j++) { if (wallRelevant.e[j]) { Accum_e_from_a(af[j],e, eDaf[j]); } else { eDaf[j] = 0.0; } } /* Now distribute {eDaf} over {eDc}: */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0,0.0,0.0,0.0}; } if (grad) { for (j = 0; j < NF; j++) { if (wallRelevant.e[j]) { ??? f = wall[j]; ??? a = f.pa^; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; { Distribute_eDa(un, vn, wn, eDaf[j]); } } } } } } } /* END Eval */ char * SELF_Name(SELF_T *erg)== { return "Area(rarea= " & Fmt.Real(erg->area, Fmt.Style.Fix, prec = 3) & ")" } /* END Name */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/CmpVolEnergy.c /* See {CmpVolEnergy.h} */ // #INCLUDE #include // #INCLUDE #include // #INCLUDE // #INCLUDE CONST Zero == 0.0; TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ polyRelevant: REF bool_vec_t; /* TRUE if cell is relevant */ vp: REF double_vec_t; /* (Work) Volume of each cell */ eDvp: REF double_vec_t; /* (Work) Derivate of energy rel. to volume cells */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0/((double)top->cell.ne); erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->polyRelevant = bool_vec_new(top->cell.ne); /* Allocate volume tables: */ erg->vp = double_vec_new(top->cell.ne); erg->eDvp = double_vec_new(top->cell.ne); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->cell.ne; i++){ erg->polyRelevant[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which cells are relevant to volume compression energy. A cell is relevant iff it exists, has exactly four walls being least one existing triangular wall having at least one variable corner. */ int NV = erg->top->node.ne; ??? NP = erg->top->cell.ne; bool_vec_t vVar = erg->vVar^; ??? cell = erg->top->cell^; ??? polyRelevant = erg->polyRelevant^; { assert(variable.ne == NV); vVar = variable; /* Find the relevant cells: */ for (i = 0; i < NP; i++){ polyRelevant[i] = FALSE; } for (i = 0; i < NP; i++) { ??? p = cell[i]; ??? r = Srot(cell[i]); Place_t a = Tors(r); Place_t r1 = Clock(PrevE(r)); Place_t a1 = Tors(r1); Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); Node_t w = OrgV(PrevE(a)); Node_t x = OrgV(PrevE(a1)); ??? vvar = vVar.e[u->num]) || (vVar.e[v->num]) || (vVar.e[w->num]) || (vVar.e[x->num]; Wall_t f1 = PWall(a); Wall_t f2 = PWall(PrevF(a)); Wall_t f3 = PWall(PrevF(NextE(a))); Wall_t f4 = PWall(PrevF(PrevE(a))); bool_t fvar = (f1->exists) || (f2->exists) || (f3->exists) || (f4->exists); { assert(f1 != f2) && (f2 != f3) && (f3 != f4); if ((p->exists) && (fvar) && (vvar)) { /*assert(u->exists) && (v->exists) && (w->exists) && (x->exists);*/ polyRelevant[i] = TRUE; } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NP = erg->top->cell.ne; bool_vec_t vVar = erg->vVar^; ??? polyRelevant = erg->polyRelevant^; ??? cell = erg->top->cell; ??? vp = erg->vp^; ??? eDvp = erg->eDvp^; ??? K = erg->K; ??? V = ((double)erg->volume); { void Accum_v(*u, v, w, x: r4_t; VAR vo: double) /* Compute the volume of the tetrahedron "u v w x". Also stores in {n} the cross product "(v - u) X (w - u) X (x - u)". */ { ??? uv = r4_Sub(v, u); ??? uw == r4_Sub(w, u); ??? ux == r4_Sub(x, u); ??? n == r4_cross(uv, uw, ux); { vo = vo + 1.0/6.0 * r4_Norm(n); } } Accum_v; void Accum_e_from_v(v: double; double e; VAR VAR etDv: double) /* Adds to "e" the energy term corresponding to a cell with volume "v". Also, if "grad" is true, stores in "etDv" the derivative of that term. */ { assert(v!=0.0); if (v <= 0.0) { etDv = 0.0 } else { double r = v/V; double s = 1.0/r; double r2 = r*r; double s2 = s*s; double h = r2 + s2 - 2.0; double v2 = v*v; double v3 = v2*v; double V2 == V*V; { e = e + K * h; if (grad) { etDv = 2.0 * K * ( (v/V2) - (V2/v3)); } else { etDv = 0.0; } } } } Accum_e_from_v; void Distribute_eDv(iu, iv, iw, ix: uint; eDvo: double) /* Accumulates in "eDc" the gradient of "e" relative to the corners of the tetrahedron "iu iv iw ix", given the derivative "eDv" of "e" relative to the tetrahedron's volume "v". */ { r4_t u = c[iu], v = c[iv], w = c[iw], x = c[ix]; double u1 = u[0], u2 = u[1], u3 = u[2], u4 = u[3]; double v1 = v[0], v2 = v[1], v3 = v[2], v4 = v[3]; double w1 = w[0], w2 = w[1], w3 = w[2], w4 = w[3]; double x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3]; double d1 = +u1 * (v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-w3*x2) -u2 * (v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-w3*x1) +u3 * (v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2) -(v1*(w2*x3-x2*w3)-v2*(w1*x3-x1*w3)+v3*(w1*x2-x1*w2)), d2 = +u1 * (v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4) -u2 * (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4) +u4 * (v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2) -(v1*(w2*x4-x2*w4)-v2*(w1*x4-x1*w4)+v4*(w1*x2-x1*w2)), d3 = +u2 * (v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4) -u3 * (v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4) +u4 * (v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-x2*w3) -(v2*(w3*x4-x3*w4)-v3*(w2*x4-x2*w4)+v4*(w2*x3-x2*w3)), d4 = +u1 * (v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4) -u3 * (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4) +u4 * (v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-x1*w3) -(v1*(w3*x4-x3*w4)-v3*(w1*x4-x1*w4)+v4*(w1*x3-x1*w3)); r4_t d = (r4_t){d1,d2,d3,d4}; double sum2 = d1*d1 + d2*d2 + d3*d3 + d4*d4; double term = (1.0/6.0) * (1.0/sqrt(sum2)); double d1Du1 = v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-w3*x2; double d2Du1 = v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4; double d3Du1 = Zero; double d4Du1 = v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4; r4_t dDu1 = (r4_t){d1Du1, d2Du1, d3Du1, d4Du1}, double vDu1 = term * r4_dot(d,dDu1); double eDu1 = eDvo * vDu1; double d1Du2 = - (v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-w3*x1); double d2Du2 = - (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4); double d3Du2 = v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4; double d4Du2 = Zero; r4_t dDu2 = (r4_t){d1Du2, d2Du2, d3Du2, d4Du2}, double vDu2 = term * r4_dot(d,dDu2); double eDu2 = eDvo * vDu2; double d1Du3 = v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2; double d2Du3 = Zero; double d3Du3 = - (v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4); double d4Du3 = - (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4); r4_t dDu3 = (r4_t){d1Du3, d2Du3, d3Du3, d4Du3}, double vDu3 = term * r4_dot(d,dDu3); double eDu3 = eDvo * vDu3; double d1Du4 = Zero; double d2Du4 = v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2; double d3Du4 = v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-x2*w3; double d4Du4 = v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-x1*w3; r4_t dDu4 = (r4_t){d1Du4, d2Du4, d3Du4, d4Du4}, double vDu4 = term * r4_dot(d,dDu4); double eDu4 = eDvo * vDu4; double d1Dv1 = u2 * (x3-w3) + u3 * (w2-x2) - w2*x3+w3*x2; double d2Dv1 = u2 * (x4-w4) + u4 * (w2-x2) - w2*x4+x2*w4; double d3Dv1 = Zero; double d4Dv1 = u3 * (x4-w4) + u4 * (w3-x3) - w3*x4+x3*w4; r4_t dDv1 = (r4_t){d1Dv1, d2Dv1, d3Dv1, d4Dv1}, double vDv1 = term * r4_dot(d,dDv1); double eDv1 = eDvo * vDv1; double d1Dv2 = u1 * (w3-x3) + u3 * (x1-w1) + w1*x3-w3*x1; double d2Dv2 = u1 * (w4-x4) + u4 * (x1-w1) + w1*x4-x1*w4; double d3Dv2 = u3 * (x4-w4) + u4 * (w3-x3) - w3*x4+x3*w4; double d4Dv2 = Zero; r4_t dDv2 = (r4_t){d1Dv2, d2Dv2, d3Dv2, d4Dv2}, double vDv2 = term * r4_dot(d,dDv2); double eDv2 = eDvo * vDv2; double d1Dv3 = u1 * (x2-w2) + u2 * (w1-x1) - w1*x2+x1*w2; double d2Dv3 = Zero; double d3Dv3 = u2 * (w4-x4) + u4 * (x2-w2) + w2*x4-x2*w4; double d4Dv3 = u1 * (w4-x4) + u4 * (x1-w1) + w1*x4-x1*w4; r4_t dDv3 = (r4_t){d1Dv3, d2Dv3, d3Dv3, d4Dv3}, double vDv3 = term * r4_dot(d,dDv3); double eDv3 = eDvo * vDv3; double d1Dv4 = Zero; double d2Dv4 = u1 * (x2-w2) + u2 * (w1-x1) - w1*x2+x1*w2; double d3Dv4 = u2 * (x3-w3) + u3 * (w2-x2) - w2*x3+x2*w3; double d4Dv4 = u1 * (x3-w3) + u3 * (w1-x1) - w1*x3+x1*w3; r4_t dDv4 = (r4_t){d1Dv4, d2Dv4, d3Dv4, d4Dv4}, double vDv4 = term * r4_dot(d,dDv4); double eDv4 = eDvo * vDv4; double d1Dw1 = u2 * (v3-x3) + u3 * (x2-v2) + v2*x3-v3*x2; double d2Dw1 = u2 * (v4-x4) + u4 * (x2-v2) + v2*x4-x2*v4; double d3Dw1 = Zero; double d4Dw1 = u3 * (v4-x4) + u4 * (x3-v3) + v3*x4-x3*v4; double dDw1 = (r4_t){d1Dw1, d2Dw1, d3Dw1, d4Dw1}; double vDw1 = term * r4_dot(d,dDw1); double eDw1 = eDvo * vDw1; double d1Dw2 = u1 * (x3-v3) + u3 * (v1-x1) - v1*x3+v3*x1; double d2Dw2 = u1 * (x4-v4) + u4 * (v1-x1) - v1*x4+x1*v4; double d3Dw2 = u3 * (v4-x4) + u4 * (x3-v3) + v3*x4-x3*v4; double d4Dw2 = Zero; r4_t dDw2 = (r4_t){d1Dw2, d2Dw2, d3Dw2, d4Dw2}, double vDw2 = term * r4_dot(d,dDw2); double eDw2 = eDvo * vDw2; double d1Dw3 = u1 * (v2-x2) + u2 * (x1-v1) + v1*x2-x1*v2; double d2Dw3 = Zero; double d3Dw3 = u2 * (x4-v4) + u4 * (v2-x2) - v2*x4+x2*v4; double d4Dw3 = u1 * (x4-v4) + u4 * (v1-x1) - v1*x4+x1*v4; r4_t dDw3 = (r4_t){d1Dw3, d2Dw3, d3Dw3, d4Dw3}, double vDw3 = term * r4_dot(d,dDw3); double eDw3 = eDvo * vDw3; double d1Dw4 = Zero; double d2Dw4 = u1 * (v2-x2) + u2 * (x1-v1) + v1*x2-x1*v2; double d3Dw4 = u2 * (v3-x3) + u3 * (x2-v2) + v2*x3-x2*v3; double d4Dw4 = u1 * (v3-x3) + u3 * (x1-v1) + v1*x3-x1*v3; r4_t dDw4 = (r4_t){d1Dw4, d2Dw4, d3Dw4, d4Dw4}, double vDw4 = term * r4_dot(d,dDw4); double eDw4 = eDvo * vDw4; double d1Dx1 = u2 * (w3-v3) + u3 * (v2-w2) - v2*w3+v3*w2; double d2Dx1 = u2 * (w4-v4) + u4 * (v2-w2) - v2*w4+w2*v4; double d3Dx1 = Zero; double d4Dx1 = u3 * (w4-v4) + u4 * (v3-w3) - v3*w4+w3*v4; r4_t dDx1 = (r4_t){d1Dx1, d2Dx1, d3Dx1, d4Dx1}, double vDx1 = term * r4_dot(d,dDx1); double eDx1 = eDvo * vDx1; double d1Dx2 = u1 * (v3-w3) + u3 * (w1-v1) + v1*w3-v3*w1; double d2Dx2 = u1 * (v4-w4) + u4 * (w1-v1) + v1*w4-w1*v4; double d3Dx2 = u3 * (w4-v4) + u4 * (v3-w3) + v4*w3-v3*w4; double d4Dx2 = Zero; r4_t dDx2 = (r4_t){d1Dx2, d2Dx2, d3Dx2, d4Dx2}, double vDx2 = term * r4_dot(d,dDx2); double eDx2 = eDvo * vDx2; double d1Dx3 = u1 * (w2-v2) + u2 * (v1-w1) - v1*w2+w1*v2; double d2Dx3 = Zero; double d3Dx3 = u2 * (v4-w4) + u4 * (w2-v2) + v2*w4-w2*v4; double d4Dx3 = u1 * (v4-w4) + u4 * (w1-v1) + v1*w4-w1*v4; r4_t dDx3 = (r4_t){d1Dx3, d2Dx3, d3Dx3, d4Dx3}, double vDx3 = term * r4_dot(d,dDx3); double eDx3 = eDvo * vDx3; double d1Dx4 = Zero; double d2Dx4 = u1 * (w2-v2) + u2 * (v1-w1) - v1*w2+w1*v2; double d3Dx4 = u2 * (w3-v3) + u3 * (v2-w2) - v2*w3+w2*v3; double d4Dx4 = u1 * (w3-v3) + u3 * (v1-w1) - v1*w3+w1*v3; r4_t dDx4 = (r4_t){d1Dx4, d2Dx4, d3Dx4, d4Dx4}, double vDx4 = term * r4_dot(d,dDx4); eDx4 = eDvo * vDx4 ){ if (vVar.e[iu]) { eDc[iu,0] = eDc[iu,0] + eDu1; eDc[iu,1] = eDc[iu,1] + eDu2; eDc[iu,2] = eDc[iu,2] + eDu3; eDc[iu,3] = eDc[iu,3] + eDu4; } if (vVar.e[iv]) { eDc[iv,0] = eDc[iv,0] + eDv1; eDc[iv,1] = eDc[iv,1] + eDv2; eDc[iv,2] = eDc[iv,2] + eDv3; eDc[iv,3] = eDc[iv,3] + eDv4; } if (vVar.e[iw]) { eDc[iw,0] = eDc[iw,0] + eDw1; eDc[iw,1] = eDc[iw,1] + eDw2; eDc[iw,2] = eDc[iw,2] + eDw3; eDc[iw,3] = eDc[iw,3] + eDw4; } if (vVar.e[ix]) { eDc[ix,0] = eDc[ix,0] + eDx1; eDc[ix,1] = eDc[ix,1] + eDx2; eDc[ix,2] = eDc[ix,2] + eDx3; eDc[ix,3] = eDc[ix,3] + eDx4; } } } Distribute_eDv; { /* Clear volume accumulators: */ for (j = 0; j < NP; j++){ vp[j] = 0.0; } /* Enumerate cells and accumulate cell volumes: */ for (j = 0; j < NP; j++) { if (polyRelevant[j]) { ??? t = Srot(cell[j]); Place_t a = Tors(t); Place_t t1 = Clock(PrevE(t)); Place_t a1 = Tors(t1); Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(a1))->num; { Accum_v(c[un], c[vn], c[wn], c[xn], vp[j]) } } } /* Compute energy "e" from cells volumes, and the gradient "eDvp": */ e = 0.0; for (p = 0; p < NP; p++) { if (polyRelevant[p]) { Accum_e_from_v(vp[p], e, eDvp[p]) } else { eDvp[p] = 0.0 } } /* Now distribute "eDvp" over "eDc": */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, ..}; } if (grad) { for (j = 0; j < NP; j++) { if (polyRelevant[j]) { ??? t = Srot(cell[j]); Place_t a = Tors(t); Place_t t1 = Clock(PrevE(t)); Place_t a1 = Tors(t1); Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(a1))->num; { Distribute_eDv(un, vn, wn, xn, eDvp[j]) } } } } } } } /* END Eval */ char * SELF_Name(SELF_T *erg)== { return "Compr(iVol = " & Fmt.Real(erg->volume, Fmt.Style.Fix, prec = 3) & ")" } /* END Name */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/CoherentEnergy.c /* See {CoherentEnergy.h} */ // #INCLUDE #include #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE CONST Zero == 0.0; Epsilon == 0.0000000001; TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ bool_vec_t wallRelevant; /* TRUE if wall is relevant */ prodet: REF double_vec_t; /* The product of the determinants of the two tetrahedra incident in each internal wall */ eDprodet: REF double_vec_t; /* (Work) Derivate of energy relative to the product of determinants. */ Wa,Wb,Wc,Wd : r4_t; /* 4D viewing matrix */ Data4Radius: double; /* Radius of nodes in R^{4} */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0/((double)top->wall.ne); erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->wallRelevant = bool_vec_new(top->wall.ne); /* Allocate product determinant tables: */ erg->prodet = double_vec_new(top->wall.ne); erg->eDprodet = double_vec_new(top->wall.ne); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->wall.ne; i++){ erg->wallRelevant.e[i] = FALSE; } /* Compute the 4D matrix of viewing */ CalcV4Matrix(erg); erg->Data4Radius = 1.43215593075614510; } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which triangular walls are relevant to "Coherent" energy. A wall is relevant iff it exists, has at least one variable corner and is an internal wall (i.e. has exactly two tetrahedra incident to it) and least one tetrahedra is an existing tetrahedron. */ int NV = erg->top->node.ne; int NF = erg->top->wall.ne; bool_vec_t vVar = erg->vVar^; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant walls: */ for (i = 0; i < NP; i++){ polyRelevant[i] = FALSE; } for (i = 0; i < NP; i++) { ??? p = cell[i]; ??? r = Srot(cell[i]); Place_t a = Tors(r); Place_t r1 = Clock(PrevE(r)); Place_t a1 = Tors(r1); Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); Node_t w = OrgV(PrevE(a)); Node_t x = OrgV(PrevE(a1)); ??? vvar = vVar.e[u->num]) || (vVar.e[v->num]) || (vVar.e[w->num]) || (vVar.e[x->num]; Wall_t f1 = PWall(a); Wall_t f2 = PWall(PrevF(a)); Wall_t f3 = PWall(PrevF(NextE(a))); Wall_t f4 = PWall(PrevF(PrevE(a))); { assert(f1 != f2) && (f2 != f3) && (f3 != f4); if ((p->exists) && (vvar)) { assert(u->exists) && (v->exists) && (w->exists) && (x->exists); polyRelevant[i] = TRUE; } } } } } /* END DefVar */ void CalcV4Matrix(erg: T) /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ VAR double norm; { ??? From4 = erg->From4; ??? To4 = erg->To4; ??? Up4 = erg->Up4; ??? Over4 = erg->Over4; ??? Wa = erg->Wa; ??? Wb = erg->Wb; ??? Wc = erg->Wc; ??? Wd = erg->Wd; { /* Calculate Wd, the 4th coordinate basis vector and line-of-sight. */ Wd = r4_Sub(To4,From4); norm = r4_Norm(Wd); if (norm < Epsilon) { fprintf(stderr,"4D To Point and From Point are the same\n"); Process.Exit¦(1); } Wd = r4_Scale(1.0/norm, Wd); /* Calculate Wa, the X-axis basis vector. */ Wa = r4_cross(Up4,Over4,Wd); norm = r4_Norm(Wa); if (norm < Epsilon) { fprintf(stderr, "4D up, over and view vectors are not perpendicular\n"); Process.Exit¦(1); } Wa = r4_Scale(1.0/norm, Wa); /* Calculate Wb, the perpendicularized Up vector. */ Wb = r4_cross(Over4,Wd,Wa); norm = r4_Norm(Wb); if (norm < Epsilon) { fprintf(stderr,"Invalid 4D over vector\n"); Process.Exit¦(1); } Wb = r4_Scale(1.0/norm, Wb); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ Wc = r4_cross(Wd,Wa,Wb); } } CalcV4Matrix; void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NP = erg->top->cell.ne; ??? cell = erg->top->cell^; bool_vec_t vVar = erg->vVar^; ??? polyRelevant = erg->polyRelevant^; ??? det = erg->det^; ??? eDdet = erg->eDdet^; ??? K = erg->K; ??? Slope = Math.pow(10.0, 2.0); ??? Data4Radius = erg->Data4Radius; ??? Wa = erg->Wa; ??? Wb = erg->Wb; ??? Wc = erg->Wc; { r3_t ProjectTo3D(num: uint) r3_t c3 ; { ??? TempV = r4_Sub(c[num], erg->From4); double rtemp = 1.0 / Data4Radius; { c3[0] = rtemp * r4_dot(TempV, erg->Wa); c3[1] = rtemp * r4_dot(TempV, erg->Wb); c3[2] = rtemp * r4_dot(TempV, erg->Wc); return c3; } } ProjectTo3D; void Accum_det(*U, V, W, X: uint; VAR dto: double) /* Compute the determinat of the tetrahedron "u v w x" in R^{3}. */ { ??? pu = ProjectTo3D(U); ??? pv = ProjectTo3D(V); ??? pw = ProjectTo3D(W); ??? px = ProjectTo3D(X); r4_t a == (r4_t){pu[0], pu[1], pu[2], 1.0}; r4_t b == (r4_t){pv[0], pv[1], pv[2], 1.0}; r4_t c == (r4_t){pw[0], pw[1], pw[2], 1.0}; r4_t d == (r4_t){px[0], px[1], px[2], 1.0}; { dto = dto + r4_det(a,b,c,d); } } Accum_det; void Accum_e_from_det(det: double; double e; VAR VAR eDdet: double) /* Adds to "e" the energy term corresponding to a cell with determinant "det". Also, if "grad" is true, stores in "eDdet" the derivative of that term. */ { ??? d2 = det * det; ??? sq = sqrt(1.0+d2); ??? h = Slope * (sq-det); { e = e + K * h; if (grad) { eDdet = K * (Slope*(det/sq-1.0) + 2.0 * det); } else { eDdet = 0.0; } } } Accum_e_from_det; void Distribute_eDdet( uint *iu,iv,iw,ix; eDdet: double) /* Accumulates in "eDc" the gradient of "e" relative to the corners of the tetrahedron "iu iv iw ix", given the derivative "eDdet" of "e" relative to the tetrahedron's determinant "det". */ { double rtemp = 1.0 / Data4Radius; double wa0 = Wa[0], wa1 = Wa[1], wa2 = Wa[2], wa3 = Wa[3]; double wb0 = Wb[0], wb1 = Wb[1], wb2 = Wb[2], wb3 = Wb[3]; double wc0 = Wc[0], wc1 = Wc[1], wc2 = Wc[2], wc3 = Wc[3]; r3_t pu = ProjectTo3D(iu); r3_t pv = ProjectTo3D(iv); r3_t pw = ProjectTo3D(iw); r3_t px = ProjectTo3D(ix); double pu0 = pu[0], pu1 = pu[1], pu2 = pu[2]; double pv0 = pv[0], pv1 = pv[1], pv2 = pv[2]; double pw0 = pw[0], pw1 = pw[1], pw2 = pw[2]; double px0 = px[0], px1 = px[1], px2 = px[2]; double A0 = pw2 - px2; double A1 = pw1 - px1; double A2 = pw1 * px2 - px1 * pw2; double A = pv1 * A0 - pv2 * A1 + A2; double B0 = pw2 - px2; double B1 = pw0 - px0; double B2 = pw0 * px2 - px0 * pw2; double B = pv0 * B0 - pv2 * B1 + B2; double C0 = pw1 - px1; double C1 = pw0 - px0; double C2 = pw0 * px1 - px0 * pw1; double C = pv0 * C0 - pv1 * C1 + C2; double D0 = pw1 * px2 - px1 * pw2; double D1 = pw0 * px2 - px0 * pw2; double D2 = pw0 * px1 - px0 * pw1; double d1Du0 = A * rtemp * wa0; double d1Du1 = A * rtemp * wa1; double d1Du2 = A * rtemp * wa2; double d1Du3 = A * rtemp * wa3; double d2Du0 = B * rtemp * wb0; double d2Du1 = B * rtemp * wb1; double d2Du2 = B * rtemp * wb2; double d2Du3 = B * rtemp * wb3; double d3Du0 = C * rtemp * wc0; double d3Du1 = C * rtemp * wc1; double d3Du2 = C * rtemp * wc2; double d3Du3 = C * rtemp * wc3; double d4Du0 = Zero; double d4Du1 = Zero; double d4Du2 = Zero; double d4Du3 = Zero; double detDu0 = d1Du0 - d2Du0 + d3Du0 - d4Du0; double detDu1 = d1Du1 - d2Du1 + d3Du1 - d4Du1; double detDu2 = d1Du2 - d2Du2 + d3Du2 - d4Du2; double detDu3 = d1Du3 - d2Du3 + d3Du3 - d4Du3; double eDu0 = eDdet * detDu0; double eDu1 = eDdet * detDu1; double eDu2 = eDdet * detDu2; double eDu3 = eDdet * detDu3; double d1Dv0 = pu0 * rtemp * ( A0 * wb0 - A1 * wc0); double d1Dv1 = pu0 * rtemp * ( A0 * wb1 - A1 * wc1); double d1Dv2 = pu0 * rtemp * ( A0 * wb2 - A1 * wc2); double d1Dv3 = pu0 * rtemp * ( A0 * wb3 - A1 * wc3); double d2Dv0 = pu1 * rtemp * ( B0 * wa0 - B1 * wc0); double d2Dv1 = pu1 * rtemp * ( B0 * wa1 - B1 * wc1); double d2Dv2 = pu1 * rtemp * ( B0 * wa2 - B1 * wc2); double d2Dv3 = pu1 * rtemp * ( B0 * wa3 - B1 * wc3); double d3Dv0 = pu2 * rtemp * ( C0 * wa0 - C1 * wb0); double d3Dv1 = pu2 * rtemp * ( C0 * wa1 - C1 * wb1); double d3Dv2 = pu2 * rtemp * ( C0 * wa2 - C1 * wb2); double d3Dv3 = pu2 * rtemp * ( C0 * wa3 - C1 * wb3); double d4Dv0 = rtemp * ( D0 * wa0 - D1 * wb0 + D2 * wc0); double d4Dv1 = rtemp * ( D0 * wa1 - D1 * wb1 + D2 * wc1); double d4Dv2 = rtemp * ( D0 * wa2 - D1 * wb2 + D2 * wc2); double d4Dv3 = rtemp * ( D0 * wa3 - D1 * wb3 + D2 * wc3); double detDv0 = d1Dv0 - d2Dv0 + d3Dv0 - d4Dv0; double detDv1 = d1Dv1 - d2Dv1 + d3Dv1 - d4Dv1; double detDv2 = d1Dv2 - d2Dv2 + d3Dv2 - d4Dv2; double detDv3 = d1Dv3 - d2Dv3 + d3Dv3 - d4Dv3; double eDv0 = eDdet * detDv0; double eDv1 = eDdet * detDv1; double eDv2 = eDdet * detDv2; double eDv3 = eDdet * detDv3; double d1Dw0 = pu0 * rtemp * ( wc0 * (pv1-px1) + wb0 * (px2-pv2)); double d1Dw1 = pu0 * rtemp * ( wc1 * (pv1-px1) + wb1 * (px2-pv2)); double d1Dw2 = pu0 * rtemp * ( wc2 * (pv1-px1) + wb2 * (px2-pv2)); double d1Dw3 = pu0 * rtemp * ( wc3 * (pv1-px1) + wb3 * (px2-pv2)); double d2Dw0 = pu1 * rtemp * ( wc0 * (pv0-px0) + wa0 * (px2-pv2)); double d2Dw1 = pu1 * rtemp * ( wc1 * (pv0-px0) + wa1 * (px2-pv2)); double d2Dw2 = pu1 * rtemp * ( wc2 * (pv0-px0) + wa2 * (px2-pv2)); double d2Dw3 = pu1 * rtemp * ( wc3 * (pv0-px0) + wa3 * (px2-pv2)); double d3Dw0 = pu2 * rtemp * ( wb0 * (pv0-px0) + wa0 * (px1-pv1)); double d3Dw1 = pu2 * rtemp * ( wb1 * (pv0-px0) + wa1 * (px1-pv1)); double d3Dw2 = pu2 * rtemp * ( wb2 * (pv0-px0) + wa2 * (px1-pv1)); double d3Dw3 = pu2 * rtemp * ( wb3 * (pv0-px0) + wa3 * (px1-pv1)); double d4Dw0 = rtemp * ( pv0 * (px2*wb0-px1*wc0) + pv1 * (px0*wc0-px2*wa0) + pv2 * (px1*wa0-px0*wb0)); double d4Dw1 = rtemp * ( pv0 * (px2*wb1-px1*wc1) + pv1 * (px0*wc1-px2*wa1) + pv2 * (px1*wa1-px0*wb1)); double d4Dw2 = rtemp * ( pv0 * (px2*wb2-px1*wc2) + pv1 * (px0*wc2-px2*wa2) + pv2 * (px1*wa2-px0*wb2)); double d4Dw3 = rtemp * ( pv0 * (px2*wb3-px1*wc3) + pv1 * (px0*wc3-px2*wa3) + pv2 * (px1*wa3-px0*wb3)); double detDw0 = d1Dw0 - d2Dw0 + d3Dw0 - d4Dw0; double detDw1 = d1Dw1 - d2Dw1 + d3Dw1 - d4Dw1; double detDw2 = d1Dw2 - d2Dw2 + d3Dw2 - d4Dw2; double detDw3 = d1Dw3 - d2Dw3 + d3Dw3 - d4Dw3; double eDw0 = eDdet * detDw0; double eDw1 = eDdet * detDw1; double eDw2 = eDdet * detDw2; double eDw3 = eDdet * detDw3; double d1Dx0 = pu0 * rtemp * ( wc0 * (pw1-pv1) + wb0 * (pv2-pw2)); double d1Dx1 = pu0 * rtemp * ( wc1 * (pw1-pv1) + wb1 * (pv2-pw2)); double d1Dx2 = pu0 * rtemp * ( wc2 * (pw1-pv1) + wb2 * (pv2-pw2)); double d1Dx3 = pu0 * rtemp * ( wc3 * (pw1-pv1) + wb3 * (pv2-pw2)); double d2Dx0 = pu1 * rtemp * ( wc0 * (pw0-pv0) + wa0 * (pv2-pw2)); double d2Dx1 = pu1 * rtemp * ( wc1 * (pw0-pv0) + wa1 * (pv2-pw2)); double d2Dx2 = pu1 * rtemp * ( wc2 * (pw0-pv0) + wa2 * (pv2-pw2)); double d2Dx3 = pu1 * rtemp * ( wc3 * (pw0-pv0) + wa3 * (pv2-pw2)); double d3Dx0 = pu2 * rtemp * ( wb0 * (pw0-pv0) + wa0 * (pv1-pw1)); double d3Dx1 = pu2 * rtemp * ( wb1 * (pw0-pv0) + wa1 * (pv1-pw1)); double d3Dx2 = pu2 * rtemp * ( wb2 * (pw0-pv0) + wa2 * (pv1-pw1)); double d3Dx3 = pu2 * rtemp * ( wb3 * (pw0-pv0) + wa3 * (pv1-pw1)); double d4Dx0 = rtemp * ( pv0 * (pw1*wc0-pw2*wb0) + pv1 * (pw2*wa0-pw0*wc0) + pv2 * (pw0*wb0-pw1*wa0)); double d4Dx1 = rtemp * ( pv0 * (pw1*wc1-pw2*wb1) + pv1 * (pw2*wa1-pw0*wc1) + pv2 * (pw0*wb1-pw1*wa1)); double d4Dx2 = rtemp * ( pv0 * (pw1*wc2-pw2*wb2) + pv1 * (pw2*wa2-pw0*wc2) + pv2 * (pw0*wb2-pw1*wa2)); double d4Dx3 = rtemp * ( pv0 * (pw1*wc3-pw2*wb3) + pv1 * (pw2*wa3-pw0*wc3) + pv2 * (pw0*wb3-pw1*wa3)); double detDx0 = d1Dx0 - d2Dx0 + d3Dx0 - d4Dx0; double detDx1 = d1Dx1 - d2Dx1 + d3Dx1 - d4Dx1; double detDx2 = d1Dx2 - d2Dx2 + d3Dx2 - d4Dx2; double detDx3 = d1Dx3 - d2Dx3 + d3Dx3 - d4Dx3; double eDx0 = eDdet * detDx0; double eDx1 = eDdet * detDx1; double eDx2 = eDdet * detDx2; double eDx3 = eDdet * detDx3; { if (vVar.e[iu]) { eDc[iu,0] = eDc[iu,0] + eDu0; eDc[iu,1] = eDc[iu,1] + eDu1; eDc[iu,2] = eDc[iu,2] + eDu2; eDc[iu,3] = eDc[iu,3] + eDu3; } if (vVar.e[iv]) { eDc[iv,0] = eDc[iv,0] + eDv0; eDc[iv,1] = eDc[iv,1] + eDv1; eDc[iv,2] = eDc[iv,2] + eDv2; eDc[iv,3] = eDc[iv,3] + eDv3; } if (vVar.e[iw]) { eDc[iw,0] = eDc[iw,0] + eDw0; eDc[iw,1] = eDc[iw,1] + eDw1; eDc[iw,2] = eDc[iw,2] + eDw2; eDc[iw,3] = eDc[iw,3] + eDw3; } if (vVar.e[ix]) { eDc[ix,0] = eDc[ix,0] + eDx0; eDc[ix,1] = eDc[ix,1] + eDx1; eDc[ix,2] = eDc[ix,2] + eDx2; eDc[ix,3] = eDc[ix,3] + eDx3; } } } Distribute_eDdet; { /* Clear determinant accumulators: */ for (j = 0; j < NP; j++){ det[j] = 0.0; } /* Enumerate cells and accumulate cell determinants: */ for (j = 0; j < NP; j++) { if (polyRelevant[j]) { ??? t = Srot(cell[j]); Place_t a = Tors(t); Place_t t1 = Clock(PrevE(t)); Place_t a1 = Tors(t1); Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(a1))->num; { Accum_det(un, vn, wn, xn, det[j]) } } } /* Compute energy "e" from cells determinants, and the gradient "eDdet": */ e = 0.0; for (p = 0; p < NP; p++) { if (polyRelevant[p]) { Accum_e_from_det(det[p], e, eDdet[p]) } else { eDdet[p] = 0.0 } } /* Now distribute "eDdet" over "eDc": */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, ..}; } if (grad) { for (j = 0; j < NP; j++) { if (polyRelevant[j]) { ??? t = Srot(cell[j]); Place_t a = Tors(t); Place_t t1 = Clock(PrevE(t)); Place_t a1 = Tors(t1); Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(a1))->num; { Distribute_eDdet(un, vn, wn, xn, eDdet[j]) } } } } } } } /* END Eval */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Coherent()" } /* END Name */ { } CoherentEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Curvature1D.c /* See {Curvature1D.h} */ // #INCLUDE // #INCLUDE // #INCLUDE #include // #INCLUDE // #INCLUDE CONST zero == (r4_t){0.0,0.0,0.0,0.0}; INIT_STACK_SIZE == 100000; Epsilon == 0.0000000001; VAR str,stc: Stat.T; /* statistical accumulators to the number of "root" elements and the number of "children" elements inside each "root" element. */ TYPE bool_vec_t == ARRAY OF bool_t; StackE == REF Edge_vec_t; Number == RECORD INTEGER nre; /* number of "root" @{edge->?}s. */ uint nce; /* number of "children" @{edge->?}s inside each "root" @{edge->?}.*/ } REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ Number num; /* Number of "root" and "children" @{edge->?}s*/ Chil@{Edge->?}: REF ARRAY OF StackE; /* The "children" @{edge->?}s */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } void SaveE( StackE *Stack; uint *top; @{Edge->?} *@{edge->?}; ) /* Save the edge "@{edge->?}" on the stack "Stack" */ { Stack.El[top] = @{edge->?}; top = top +1 } /* END SaveE */ Number Statistics(ElemTableRec_t *top) Number *num; { for (i = 0; i < top->NE; i++){ ??? e = top->edge[i]; double = e->root; { Stat.Accum(str,er); if (er == 20.0){ Stat.Accum(stc,er); } /* 0.0 */ } } num.nre = FLOOR(str.maximum)+1; num.nce = FLOOR(stc->num); return num; } /* END Statistics */ PROCEDURE CropChil@{Edge->?}s( ElemTableRec_t *top; Number *num; ): REF ARRAY OF StackE == /* Crop the "children" @{edge->?}s for each "root" @{edge->?}. */ topj : REF uint_vec_t; { /* initialize the "top" indexes for each of the "num.nre" stacks of @{edge->?}s. */ topj = NEW(REF uint_vec_t , num.nre); for (k = 0; k < num.nre; k++){ topj[k] = 0; } ??? t = NEW(REF ARRAY OF StackE, num.nre); { for (k = 0; k < num.nre; k++) { t[k] = Edge_vec_new(INIT_STACK_SIZE); } for (j = 0; j < top->NE; j++) { ??? e = top->edge[j]; int er = e->root; DO if (er!=-1){ SaveE(t[er],topj[er],e); } } } return t; } } /* END CropChil@{Edge->?}s */ SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0; erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->num = Statistics(top); erg->Chil@{Edge->?} = CropChil@{Edge->?}s(top,erg->num); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { int NV = erg->top->node.ne; ??? vVar = erg->vVar^; { assert((variable.ne) == NV); vVar = variable; } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { ??? NV = erg->top->node.ne; ??? K = erg->K; ??? vVar = erg->vVar^; ??? Chil@{Edge->?} = erg->Chil@{Edge->?}; ??? num = erg->num; { void AddTerm(*iu,iv,iw: uint) /* Adds one term of the curvature energy to "e" (and its derivative to "eDc, if "grad" is TRUE). The terms correspond to the edge "e1 == u v" and the edge "e2 == u w". v w \ / \ / e1 \ / e2 \/ u */ double eterm ; eDdu, eDdv, eDdw: r4_t; { ??? u = c[iu]; ??? v = c[iv]; ??? w = c[iw]; { term(u,v,w, eterm, eDdu, eDdv, eDdw); e = e + eterm; if (grad) { if (vVar.e[iu]) { eDc[iu] = r4_Add(eDc[iu],eDdu); } if (vVar.e[iv]) { eDc[iv] = r4_Add(eDc[iv],eDdv); } if (vVar.e[iw]) { eDc[iw] = r4_Add(eDc[iw],eDdw); } } } } AddTerm; void term( u,v,w: r4_t; double *eterm; VAR dedu,dedv,dedw: r4_t; ) VAR dedDv,dedDw: r4_t; { r4_t Dv = r4_Sub(v, u); /* V */ r4_t Dw = r4_Sub(w, u); /* V */ { Eangle(Dv,Dw, eterm, dedDv,dedDw); dedv = dedDv; /* V */ dedw = dedDw; /* V */ dedu = Neg(Add(dedDv,dedDw)); /* V */ } } term; void Eangle( *R,S: r4_t; double *E; VAR EDR,EDS: r4_t; ) /* Given two vectors "R" and "S" compute the "cos" of the angle between the vectors, the curvature term and the derivatives of energy respect to the two vectors: eeDR and eeDS. */ { double m = r4_Norm(R) + Epsilon; double n = r4_Norm(S) + Epsilon; double o = r4_dot(R, S); double d == m*n; double q == o/d; { if (d!=0.0) { E = K * (1.0 + q); if (grad) { ??? eDq = 1.0 * K; ??? eDo = eDq / d; ??? eDd = - eDq * q / d; ??? eDm = eDd * n; ??? eDn = eDd * m; { EDR = r4_Mix(eDo, S, eDm/m, R); EDS = r4_Mix(eDo, R, eDn/n, S); } } } } } Eangle; { /* Initialize */ for (i = 0; i < NV; i++){ eDc[i] = zero; } /* Compute energy "e", and the gradient "eDc": */ e = 0.0; for (i = 0; i < num.nre; i++) { for (j = 0; j < num.nce; j++) { for (k = j+1; k < num.nce; k++) { if ((Chil@{Edge->?}[i,j]->exists) && (Chil@{Edge->?}[i,k]->exists)) { if ((Adjacent(Chil@{Edge->?}[i,j], Chil@{Edge->?}[i,k]))) { uint u1 = OrgV(Chil@{Edge->?}[i,j].pa)->num; uint v1 = OrgV(Clock(Chil@{Edge->?}[i,j].pa))->num; uint u2 = OrgV(Chil@{Edge->?}[i,k].pa)->num; uint v2 = OrgV(Clock(Chil@{Edge->?}[i,k].pa))->num; { if (u1 == u2) { AddTerm(u1,v1,v2); } else if (v1 == u2){ AddTerm(v1,u1,v2); } else if (u1 == v2){ AddTerm(u1,v1,u2); } else if (v1 == v2){ AddTerm(v1,u1,u2); } } } } } } } } } } /* END Eval */ bool_t Adjacent(e1,e2: @{Edge->?}) { ??? u1 = OrgV(e1.pa)->num; ??? v1 = OrgV(Clock(e1.pa))->num; ??? u2 = OrgV(e2.pa)->num; ??? v2 = OrgV(Clock(e2.pa))->num; { if ((u1 == u2) || (u1 == v2) || (v1 == v2) || ((v1 == u2) )){ return TRUE; } else { return FALSE; } } } /* END Adjacent */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Curv1D()" } /* END Name */ { } Curvature1D. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Curvature2D.c /* See {Curvature2D.h} */ // #INCLUDE // #INCLUDE #include // #INCLUDE // #INCLUDE CONST zero == (r4_t){0.0,0.0,0.0,0.0}; Epsilon == 1.0d-9; TYPE bool_vec_t == ARRAY OF bool_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0; erg->top = top; erg->vVar = bool_vec_new(top->node.ne); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { int NV = erg->top->node.ne; ??? vVar = erg->vVar^; { assert((variable.ne) == NV); vVar = variable; } } /* END DefVar */ PROCEDURE @{Edge->?}BelongsToOriginalWall(Place_t @p, ElemTableRec_t *top): bool_t == /* TRUE if the edge component of "a" belongs to a wall of the original map. */ Place_t b = a; { if ((top->edge[PEdge(a)->num]->root!=-1)){ return FALSE; } /* Check if any wall incident to "a" belongs to a wall of the original map. */ do { if ((top->wall[PWall(b)->num]->root!=-1)){ return TRUE; } b = NextF(b) } while (b != a); return FALSE; } /* END @{Edge->?}BelongsToOriginalWall */ PROCEDURE PiecesOfOriginalWall(Place_t @p, ElemTableRec_t *top): ARRAY [0..1] OF Place_t == /* Assumes that the edge component of "a" belongs to a wall of the original map. Returns the two new walls incident to "a" that were part of that old wall. */ Place_t fg[1+1]; { /* Look for the first wall: */ while (top->wall[PWall(a)->num]->root == -1){ a = NextF(a); } fg[0] = a; /* Look for second wall. */ a = NextF(a); while (top->wall[PWall(a)->num]->root == -1){ a = NextF(a); } fg[1] = a; assert(fg[0]!=fg[1]); return fg; } /* END PiecesOfOriginalWall */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { ??? NV = erg->top->node.ne; ??? K = erg->K; ??? vVar = erg->vVar^; ??? top = erg->top; { void AddTerm(*iu,iv,iw,ix: uint) /* Adds one term of the curvature energy to "e" (and its derivative to "eDc, if "grad" is TRUE). The terms correspond to the walls "f1 == u v w" and "f2 == u w x". See the follow picture: v /|\ / | \ / | \ / / | \ \ ------ w / | \ x ----- \ \ f1 | f2 / / \ | / \ | / \ | / \|/ u */ double eterm ; eDdu, eDdv, eDdw, eDdx: r4_t; { ??? u = c[iu]; ??? v = c[iv]; ??? w = c[iw]; ??? x = c[ix]; { term(u,v,w,x, eterm, eDdu, eDdv, eDdw, eDdx); e = e + eterm; if (grad) { if (vVar.e[iu]) { eDc[iu] = r4_Add(eDc[iu],eDdu); } if (vVar.e[iv]) { eDc[iv] = r4_Add(eDc[iv],eDdv); } if (vVar.e[iw]) { eDc[iw] = r4_Add(eDc[iw],eDdw); } if (vVar.e[ix]) { eDc[ix] = r4_Add(eDc[ix],eDdx); } } } } AddTerm; void term(u,v,w,x: r4_t; double *eterm; VAR dedu,dedv,dedw,dedx: r4_t; ) VAR dedDv,dedDw,dedDx: r4_t; { r4_t Dv = r4_Sub(v, u); /* V */ r4_t Dw = r4_Sub(w, u); /* V */ r4_t Dx = r4_Sub(x, u); { EangleAux(Dv,Dw, Dx, eterm, dedDv,dedDw,dedDx); dedv = dedDv; /* V */ dedw = dedDw; /* V */ dedx = dedDx; /* V */ dedu = Neg(Add(Add(dedDv,dedDw),dedDx)); } } term; void EangleAux(f,a,b: r4_t; double *eterm; VAR dedf,deda,dedb: r4_t; ) /* compute the derivative of the orthogonal vectors "f" and "g" where "f== s - Proj(s,r)" and "g == r". */ VAR dedr,deds: r4_t; { ??? m = r4_dot(f,f)+Epsilon; /* S */ ??? u = r4_dot(f,a); /* S */ ??? v = r4_dot(f,b); /* S */ ??? U = u/m; /* S */ ??? V = v/m; /* S */ ??? Uf = r4_Scale(U,f); /* V */ ??? Vf = r4_Scale(V,f); /* V */ ??? R = r4_Sub(a,Uf); /* V */ ??? S = r4_Sub(b,Vf); /* V */ { Eangle(R,S,eterm,dedr,deds); ??? dedV = - Dot(deds,f); /* S */ ??? dedU = - Dot(dedr, f); /* S */ ??? dedu = dedU/m; /* S */ ??? dedv = dedV/m; /* S */ ??? dedm = (-1.0/m) * (dedU*U + dedV*V); /* S */ ??? dedm2 = r4_Scale(2.0,f); /* S */ ??? dedm2f = r4_Scale(dedm, dedm2); /* V */ ??? dedua = r4_Scale(dedu, a); /* V */ ??? dedvb = r4_Scale(dedv, b), /* V */ ??? dedrU = r4_Neg(r4_Scale(U, dedr)); /* V */ ??? dedsV = r4_Neg(r4_Scale(V, deds)); /* V */ ??? t1 = r4_Add(dedm2f,dedua); /* V */ ??? t2 = r4_Add(t1, dedvb); /* V */ ??? t3 = r4_Add(t2, dedrU); /* V */ ??? t4 = r4_Add(t3, dedsV); /* V */ ??? deduf = r4_Scale(dedu, f); /* V */ ??? dedvf = r4_Scale(dedv, f); /* V */ ??? c1 = r4_Add(deduf, dedr); /* V */ ??? d1 = r4_Add(dedvf, deds); /* V */ { dedf = t4; deda = c1; dedb = d1; } } } EangleAux; void Eangle( *R,S: r4_t; double *E; VAR EDR,EDS: r4_t; ) /* Given two vectors "R" and "S" compute the "cos" of the angle between the vectors, the curvature term and the derivatives of energy respect to the two vectors: eeDR and eeDS. */ { ??? m = r4_Norm(R) + Epsilon; ??? n = r4_Norm(S) + Epsilon; ??? o = r4_dot(R, S); double d = m*n; double q = o/d; { if (d!=0.0) { E = K * (1.0 + q); if (grad) { ??? eDq = 1.0 * K; ??? eDo = eDq / d; ??? eDd = - eDq * q / d; ??? eDm = eDd * n; ??? eDn = eDd * m; { EDR = r4_Mix(eDo, S, eDm/m, R); EDS = r4_Mix(eDo, R, eDn/n, S); } } } } } Eangle; { /* Initialize */ for (i = 0; i < NV; i++){ eDc[i] = zero; } /* Compute energy "e", and the gradient "eDr": */ e = 0.0; for (i = 0; i < top->NE; i++) { ??? a = top->edge[i].pa; { if ((@{Edge->?}BelongsToOriginalWall(a,top))) { ??? fg = PiecesOfOriginalWall(a, top); ??? f = fg[0]; ??? g = fg[1]; Node_t u = OrgV(f)->num; Node_t v = OrgV(Clock(f))->num; ??? w1 = OrgV(PrevE(f))->num; ??? w2 = OrgV(PrevE(g))->num; { AddTerm(u, v, w1, w2) } } } } } } } /* END Eval */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Curv2D()" } /* END Name */ { } Curvature2D. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Curvature3D.c /* See {Curvature3D.h} */ // #INCLUDE #define Curvature3D_C_author \ "Modified by L.A.P.Lozada on 2000-11-18." #include // #INCLUDE // #INCLUDE CONST zero == (r4_t){0.0,0.0,0.0,0.0}; Epsilon == 0.0000000001; TYPE bool_vec_t == ARRAY OF bool_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ bool_vec_t wallRelevant; /* TRUE if wall is relevant */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0; erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->wallRelevant = bool_vec_new(top->wall.ne); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->wall.ne; i++){ erg->wallRelevant.e[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which wall are relevant to the curvature energy. A wall is relevant iff has exactly two cell incident to it. */ int NV = erg->top->node.ne; int NF = erg->top->wall.ne; bool_vec_t vVar = erg->vVar^; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant walls: */ for (i = 0; i < NF; i++){ wallRelevant.e[i] = FALSE; } for (i = 0; i < NF; i++) { ??? f = wall[i]; ??? a = f.pa; ??? p1 = Pneg(a); ??? p2 = Ppos(a); { if (((p1!=NULL) && (p2!=NULL))) { wallRelevant.e[i] = TRUE; } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; int NF = erg->top->wall.ne; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; ??? K = erg->K; ??? vVar = erg->vVar^; { void AddTerm(*iu,iv,iw,ix,iy: uint) /* Adds one term of the curvature energy to "e" (and its derivative to "eDc, if "grad" is TRUE). The terms correspond to the wall "f == u v w" shared by the tetrahedra "u v w x" (Pneg) and "u v w y" (Ppos). _ _ |\ w w /| \ /|\ /|\ / \ / | \ / | \ / / | \ / | \ / | \ / | \ x /____|____\v v/____|____\ y \ | f / \ f | / \ | / \ | / \ | / \ | / \ | / \ | / \|/ \|/ u u Pneg Ppos */ double eterm ; eDdu, eDdv, eDdw, eDdx, eDdy: r4_t; { ??? u = c[iu]; ??? v = c[iv]; ??? w = c[iw]; ??? x = c[ix]; ??? y = c[iy]; { term(u,v,w,x,y, eterm, eDdu, eDdv, eDdw, eDdx, eDdy); e = e + eterm; if (grad) { if (vVar.e[iu]) { eDc[iu] = r4_Add(eDc[iu],eDdu); } if (vVar.e[iv]) { eDc[iv] = r4_Add(eDc[iv],eDdv); } if (vVar.e[iw]) { eDc[iw] = r4_Add(eDc[iw],eDdw); } if (vVar.e[ix]) { eDc[ix] = r4_Add(eDc[ix],eDdx); } if (vVar.e[iy]) { eDc[iy] = r4_Add(eDc[iy],eDdy); } } } } AddTerm; void term(u,v,w,x,y: r4_t; double *eterm; VAR dedu,dedv,dedw,dedx,dedy: r4_t; ) VAR dedDv,dedDw,dedDx,dedDy: r4_t; { r4_t Dv = r4_Sub(v, u); /* V */ r4_t Dw = r4_Sub(w, u); /* V */ r4_t Dx = r4_Sub(x, u); /* V */ r4_t Dy == r4_Sub(y,u); /* V */ { Eangle(Dv,Dw,Dx,Dy, eterm, dedDv,dedDw,dedDx,dedDy); dedv = dedDv; /* V */ dedw = dedDw; /* V */ dedx = dedDx; /* V */ dedy = dedDy; /* V */ dedu = Neg(Add(Add(Add(dedDv,dedDw),dedDx),dedDy)); } } term; void Eangle(r,s,a,b: r4_t; double *eterm; VAR dedr,deds,deda,dedb: r4_t; ) /* compute the derivative of the orthogonal vectors "f" and "g" where "f== s - Proj(s,r)" and "g == r". */ VAR dedf,dedg: r4_t; { ??? m = Dot(r,r)+Epsilon; /* S */ ??? n = Dot(r,s); /* S */ ??? m2 = m * m; /* S */ ??? q = n/m; /* S */ ??? qr = Scale(q,r); /* V */ ??? f = Sub(s,qr); /* V */ ??? g = r; /* V */ /* Now, "f" and "g" are orthogonal */ { EangleAux(f,g,a,b,eterm,dedf,dedg,deda,dedb); ??? dedq = -r4_dot(dedf,r); /* S */ ??? dedn = dedq/m; /* S */ ??? dedm = -dedq * (n/m2); /* S */ ??? r2 = r4_Scale(2.0,r); /* V */ ??? v1 = r4_Scale(dedm, r2); /* V */ ??? v2 = r4_Scale(dedn, s); /* V */ ??? v3 = r4_Scale(-q , dedf); /* V */ ??? v4 = dedg; /* V */ ??? v12 = r4_Add(v1,v2); /* V */ ??? v123 = r4_Add(v12,v3); /* V */ ??? v1234= r4_Add(v123,v4); /* V */ ??? dednr == r4_Scale(dedn, r); /* V */ { dedr = v1234; deds = Add(dednr, dedf); } } } Eangle; void EangleAux( f,g,a,b: r4_t; double *eterm; VAR dedf,dedg,deda,dedb: r4_t; ) /* compute the derivative of the orthogonal vectors "f" and "g" where "f== s - Proj(s,r)" and "g == r". */ VAR dedr,deds: r4_t; { ??? m = r4_dot(f,f) + Epsilon; /* S */ double n = r4_dot(g,g) + Epsilon, /* S */ double u = r4_dot(f,a); /* S */ double v = r4_dot(f,b); /* S */ double x = r4_dot(g,a); /* S */ double y = r4_dot(g,b); /* S */ double U = u/m; /* S */ double V = v/m; /* S */ double X = x/n; /* S */ double Y = y/n; /* S */ double Uf = r4_Scale(U,f); /* V */ double Xg = r4_Scale(X,g); /* V */ double Vf = r4_Scale(V,f); /* V */ double Yg = r4_Scale(Y,g); /* V */ double UfXg = r4_Neg(r4_Add(Uf,Xg)); /* V */ double VfYg = r4_Neg(r4_Add(Vf,Yg)); /* V */ double R = r4_Add(a,UfXg); /* V */ double S = r4_Add(b,VfYg); /* V */ { EangleVec(R,S,eterm,dedr,deds); ??? dedY = - Dot(deds,g); /* S */ ??? dedX = - Dot(dedr, g); /* S */ ??? dedV = - Dot(deds, f); /* S */ ??? dedU = - Dot(dedr, f); /* S */ ??? dedx = dedX/n; /* S */ ??? dedy = dedY/n; /* S */ ??? dedu = dedU/m; /* S */ ??? dedv = dedV/m; /* S */ ??? dedm = (-1.0/m) * (dedU*U + dedV*V); /* S */ ??? dedn = (-1.0/n) * (dedX*X + dedY*Y); /* S */ ??? dedm2 = r4_Scale(2.0,f); /* S */ ??? dedm2f = r4_Scale(dedm, dedm2); /* V */ ??? dedua = r4_Scale(dedu, a); /* V */ ??? dedvb = r4_Scale(dedv, b); /* V */ ??? dedrU = r4_Neg(r4_Scale(U, dedr)); /* V */ ??? dedsV = r4_Neg(r4_Scale(V, deds)); /* V */ ??? t1 = r4_Add(dedm2f,dedua); /* V */ ??? t2 = r4_Add(t1, dedvb); /* V */ ??? t3 = r4_Add(t2, dedrU); /* V */ ??? t4 = r4_Add(t3, dedsV); /* V */ ??? g2 = r4_Scale(2.0,g); /* S */ ??? dedn2g = r4_Scale(dedn, g2); /* V */ ??? dedxa = r4_Scale(dedx, a); /* V */ ??? dedyb = r4_Scale(dedy, b); /* V */ ??? dedrX = r4_Neg(r4_Scale(X, dedr)); /* V */ ??? dedsY = r4_Neg(r4_Scale(Y, deds)); /* V */ ??? f1 = r4_Add(dedn2g,dedxa), /* V */ ??? f2 = r4_Add(f1, dedyb); /* V */ ??? f3 = r4_Add(f2, dedrX); /* V */ ??? f4 = r4_Add(f3, dedsY); /* V */ ??? deduf = r4_Scale(dedu, f); /* V */ ??? dedxg = r4_Scale(dedx, g); /* V */ ??? dedvf = r4_Scale(dedv, f); /* V */ ??? dedyg = r4_Scale(dedy, g); /* V */ ??? c1 = r4_Add(deduf, dedxg); /* V */ ??? c2 = r4_Add(c1, dedr); /* V */ ??? d1 = r4_Add(dedvf, dedyg); /* V */ ??? d2 = r4_Add(d1, deds); /* V */ { dedf = t4; dedg = f4; deda = c2; dedb = d2; } } } EangleAux; void EangleVec( *R,S: r4_t; double *E; VAR EDR,EDS: r4_t; ) /* Given two vectors "R" and "S" compute the "cos" of the angle between the vectors, the curvature term and the derivatives of energy respect to the two vectors: eeDR and eeDS. */ { ??? m = r4_Norm(R) + Epsilon; ??? n = r4_Norm(S) + Epsilon; ??? o = r4_dot(R, S); double d = m*n; double q = o/d; double c = (1.0 + Epsilon) - q; double c2 = c * c; { if (d!=0.0) { E = K * (1.0/c - 0.5); if (grad) { ??? eDq = 1.0/c2 * K; ??? eDo = eDq / d; ??? eDd = - eDq * q / d; ??? eDm = eDd * n; ??? eDn = eDd * m; { EDR = r4_Mix(eDo, S, eDm/m, R); EDS = r4_Mix(eDo, R, eDn/n, S); } } } } } EangleVec; { /* Initialize */ for (i = 0; i < NV; i++){ eDc[i] = zero; } /* Compute energy "e", and the gradient "eDr": */ e = 0.0; for (i = 0; i < NF; i++) { if (wallRelevant.e[i]) { ??? f = wall[i]; ??? a = f.pa; ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; { assert(xn!=yn); AddTerm(un,vn,wn,xn,yn) } } } } } } /* END Eval */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Curv3D()" } /* END Name */ { } Curvature3D. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ElasticityEnergy.c /* See {ElasticityEnergy.h} */ // #INCLUDE #include #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE CONST Pi == Math.Pi; A == LR3x3.T { (r3_t){0.0, 1.0, 1.0}, (r3_t){1.0, 0.0, 1.0}, (r3_t){1.0, 1.0, 0.0} } /* Matrix that maps the reference configuration to the repose (or relaxed) configuration (i.e. has zero elastic energy). The volume is 0.333333 . The reference configuration is a tetrahedron with nodes: r1==(0,0,0), r2==(1,0,0), r3==(0,1,0) and r4==(0,0,1). The repose configuration is a regular tetrahedron with nodes: q1==(0,0,0), q2==(0,1,1), q3==(1,1,0) and q4==(1,0,1). The Elasticity energy forces each tetrahedron has volume equal to 0.3333. */ TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; LR4x3 == ARRAY [0..3] OF r3_t; LR3x4 == ARRAY [0..2] OF r4_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ polyRelevant: REF bool_vec_t; /* TRUE if cell is relevant */ ep: REF double_vec_t; /* elasticity energy of each tetrahedron */ eDep: REF double_vec_t; /* (Work) derivative of energy rel. ep */ double volume; OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0; erg->top = top; erg->volume = (4.0/3.0)* FLOAT(Pi,double)/FLOAT(top->cell.ne,double); erg->vVar = bool_vec_new(top->node.ne); erg->polyRelevant = bool_vec_new(top->cell.ne); erg->ep = double_vec_new(top->cell.ne); erg->eDep = double_vec_new(top->cell.ne); /* Allocate determinant tables: */ /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->cell.ne; i++){ erg->polyRelevant[i] = FALSE; } } /* END DefTop */ LR4x3 Transpose_3x4(*m: LR3x4) /* Return the transpose of a matrix 3x4. */ t : LR4x3; { t[0] = (r3_t){m[0,0], m[1,0], m[2,0]}; t[1] = (r3_t){m[0,1], m[1,1], m[2,1]}; t[2] = (r3_t){m[0,2], m[1,2], m[2,2]}; t[3] = (r3_t){m[0,3], m[1,3], m[2,3]}; return t; } /* END Transpose_3x4 */ LR3x4 Transpose_4x3(*m: LR4x3) /* return the transpose of a matrix 4x3. */ t : LR3x4; { t[0] = (r4_t){m[0,0], m[1,0], m[2,0], m[3,0]}; t[1] = (r4_t){m[0,1], m[1,1], m[2,1], m[3,1]}; t[2] = (r4_t){m[0,2], m[1,2], m[2,2], m[3,2]}; return t; } /* END Transpose_4x3 */ LR4x3 Mul_4x3_3x3(*a: LR4x3; *b: LR3x3.T) /* Return the product of the matrix "a" 4x3 and matrix "b" 3x3. */ c : LR4x3; { double a00 = a[0,0], a01 = a[0,1], a02 = a[0,2]; double a10 = a[1,0], a11 = a[1,1], a12 = a[1,2]; double a20 = a[2,0], a21 = a[2,1], a22 = a[2,2]; double a30 = a[3,0], a31 = a[3,1], a32 = a[3,2]; double b00 = b[0,0], b01 = b[0,1], b02 = b[0,2]; double b10 = b[1,0], b11 = b[1,1], b12 = b[1,2]; double b20 = b[2,0], b21 = b[2,1], b22 = b[2,2]; double c00 = a00 * b00 + a01 * b10 + a02 * b20; double c01 = a00 * b01 + a01 * b11 + a02 * b21; double c02 = a00 * b02 + a01 * b12 + a02 * b22; double c10 = a10 * b00 + a11 * b10 + a12 * b20; double c11 = a10 * b01 + a11 * b11 + a12 * b21; double c12 = a10 * b02 + a11 * b12 + a12 * b22; double c20 = a20 * b00 + a21 * b10 + a22 * b20; double c21 = a20 * b01 + a21 * b11 + a22 * b21; double c22 = a20 * b02 + a21 * b12 + a22 * b22; double c30 = a30 * b00 + a31 * b10 + a32 * b20; double c31 = a30 * b01 + a31 * b11 + a32 * b21; double c32 = a30 * b02 + a31 * b12 + a32 * b22; r3_t c0 = (r3_t){c00,c01,c02}; r3_t c1 = (r3_t){c10,c11,c12}; r3_t c2 = (r3_t){c20,c21,c22}; r3_t c3 = (r3_t){c30,c31,c32}; { c[0] = c0; c[1] = c1; c[2] = c2; c[3] = c3; return c; } } /* END Mul_4x3_3x3 */ LR3x3.T Mul_3x4_4x3(*a: LR3x4; *b: LR4x3) /* Return the product of the matrix "a" 3x4 and matrix "b" 4x3. */ { double a00 = a[0,0], a01 = a[0,1], a02 = a[0,2], a03 = a[0,3]; double a10 = a[1,0], a11 = a[1,1], a12 = a[1,2], a13 = a[1,3]; double a20 = a[2,0], a21 = a[2,1], a22 = a[2,2], a23 = a[2,3]; double b00 = b[0,0], b01 = b[0,1], b02 = b[0,2]; double b10 = b[1,0], b11 = b[1,1], b12 = b[1,2]; double b20 = b[2,0], b21 = b[2,1], b22 = b[2,2]; double b30 = b[3,0], b31 = b[3,1], b32 = b[3,2]; double c00 = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30; double c01 = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31; double c02 = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32; double c10 = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30; double c11 = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31; double c12 = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32; double c20 = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30; double c21 = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31; double c22 = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32; r3_t c0 == (r3_t){c00,c01,c02}; r3_t c1 == (r3_t){c10,c11,c12}; r3_t c2 == (r3_t){c20,c21,c22}; { return LR3x3.T{c0,c1,c2}; } } /* END Mul_3x4_4x3 */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which cells are relevant to "Orientation" energy. A cell is relevant iff it exists,has at least one variable corner. */ int NV = erg->top->node.ne; ??? NP = erg->top->cell.ne; bool_vec_t vVar = erg->vVar^; ??? dell = erg->top->cell^; ??? polyRelevant = erg->polyRelevant^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant cells: */ for (i = 0; i < NP; i++){ polyRelevant[i] = FALSE; } for (i = 0; i < NP; i++) { ??? r = Srot(cell[i]); Place_t a = Tors(r); Place_t r1 = Clock(PrevE(r)); Place_t a1 = Tors(r1); Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); Node_t w = OrgV(PrevE(a)); Node_t x = OrgV(PrevE(a1)); ??? vvar = vVar.e[u->num]) || (vVar.e[v->num]) || (vVar.e[w->num]) || (vVar.e[x->num]; Wall_t f1 = PWall(a); Wall_t f2 = PWall(PrevF(a)); Wall_t f3 = PWall(PrevF(NextE(a))); Wall_t f4 = PWall(PrevF(PrevE(a))); { assert(f1 != f2) && (f2 != f3) && (f3 != f4); if (vvar) { polyRelevant[i] = TRUE; } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NP = erg->top->cell.ne; ??? polyRelevant = erg->polyRelevant^; ??? cell = erg->top->cell^; bool_vec_t vVar = erg->vVar; ??? K = erg->K; ??? ep = erg->ep; ??? eDep = erg->eDep; ??? top = erg->top; ??? alpha = erg->alpha; ??? beta = erg->beta; ??? volA = (1.0/6.0) * LR3x3.Det(A); { LR4x3 ShapeMatrix(*uint i) LR3x4 b; VAR /* _ _ | v0-u0 w0-u0 x0-u0 | B == | v1-u1 w1-u1 x1-u1 | | v2-u2 w2-u2 x2-u2 | | v3-u3 w3-u3 x3-u3 | - - */ { ??? r = Srot(top.cell[i]); Place_t a = Tors(r); ??? tv = Triangulation.TetraNegNodes(a); ??? u = c[tv[0]->num]; ??? v = c[tv[1]->num]; ??? w = c[tv[2]->num]; ??? x = c[tv[3]->num]; { b[0] = r4_Sub(v,u); b[1] = r4_Sub(w, u); b[2] = r4_Sub(x,u); return Transpose_3x4(b); } } ShapeMatrix; double ElasticEnergy(uint i) /* This procedure compute the elastic energy of a tetrahedral element. Where Delta, Gamma and Sigma are the "invariants of rotation" inside of a tetrahedron, compute although the strain tensor ("C" matrix). The metric tensor is the "T" matrix, where T == Mul(Transpose(C), C) (the matrix T is simetric). From the metric tensor, we conpute the elastic energy density: "term1+term2". Its integral over the tetrahedron T is merely the product of the elastic energy density by its volume VT in its relaxed configuration (i.e. when the elasstic energy is zero). See the section 4.2 "Calculo das forcas de elasticidade" in the Msc. Thesis "Animacao Dinamica de Corpos Elasticos" by R.L.W.L */ { ??? B = ShapeMatrix(i); ??? C = Mul_4x3_3x3(B, LR3x3.Inv(A)); /* C == B * A_1 */ ??? T = Mul_3x4_4x3(Transpose_4x3(C), C); ??? T11 = T[1,1]*T[2,2] - T[1,2]*T[1,2]; ??? T12 = T[0,1]*T[2,2] - T[1,2]*T[0,2]; ??? T13 = T[0,1]*T[1,2] - T[1,1]*T[0,2]; ??? T22 = T[0,0]*T[2,2] - T[0,2]*T[0,2]; ??? T33 = T[0,0]*T[1,1] - T[0,1]*T[0,1]; ??? Delta = T[0,0]*T11 - T[0,1]*T12 + T[0,2]*T13; ??? Sigma = T11 + T22 + T33; ??? Gamma = T[0,0] + T[1,1] + T[2,2]; ??? term1 = alpha/32.0*(Delta*Delta+1.0/(Delta*Delta)-2.0); ??? term2 = beta/6.0*(Gamma*Gamma - 3.0*Sigma); ??? P = volA*(term1 + term2); { return P; } } ElasticEnergy; void Accum_ep(uint i; VAR epo: double) /* Compute the potential energy of the tetrahedron "i" in R^{3}. */ { epo = epo + ElasticEnergy(i); } Accum_ep; void Accum_e_from_ep(ep: double; double e; VAR VAR eDep: double) /* Adds to "e" the energy term corresponding to a cell with determinant "det". Also, if "grad" is true, stores in "eDdet" the derivative of that term. */ { e = e + K * ep; if (grad) { eDep = K; } else { eDep = 0.0; } } Accum_e_from_ep; void Distribute_eDep(uint i; eDep: double) /* Accumulates in "eDc" the gradient of "e" relative to the corners of the tetrahedron "i", given the derivative "eDep" of "e" relative to the tetrahedron's elastic energy "epv". */ { ??? B = ShapeMatrix(i); ??? ??? C = Mul_4x3_3x3(B, LR3x3.Inv(A)); ??? T = Mul_3x4_4x3(Transpose_4x3(C), C); double T11 = T[1,1]*T[2,2] - T[1,2]*T[1,2]; double T12 = T[0,1]*T[2,2] - T[1,2]*T[0,2]; double T13 = T[0,1]*T[1,2] - T[1,1]*T[0,2]; double T22 = T[0,0]*T[2,2] - T[0,2]*T[0,2]; double T33 = T[0,0]*T[1,1] - T[0,1]*T[0,1]; double Delta = T[0,0]*T11 - T[0,1]*T12 + T[0,2]*T13; double Sigma = T11 + T22 + T33; double Del_3 = 1.0/(Delta*Delta*Delta); ??? t = Srot(cell[i]); Place_t a = Tors(t); Place_t t1 = Clock(PrevE(t)); Place_t a1 = Tors(t1); Node_t iu = OrgV(a)->num; Node_t iv = OrgV(NextE(a))->num; Node_t iw = OrgV(PrevE(a))->num; Node_t ix = OrgV(PrevE(a1))->num; double t00 = T[0,0], t01 = T[0,1], t02 = T[0,2]; double t11 = T[1,1], t12 = T[1,2], t22 = T[2,2]; double c00 = C[0,0], c01 = C[0,1], c02 = C[0,2]; double c10 = C[1,0], c11 = C[1,1], c12 = C[1,2]; double c20 = C[2,0], c21 = C[2,1], c22 = C[2,2]; double c30 = C[3,0], c31 = C[3,1], c32 = C[3,2]; double b00Du0 = -1.0, b01Du0 = -1.0, b02Du0 = -1.0; double b10Du0 = 0.0, b11Du0 = 0.0, b12Du0 = 0.0; double b20Du0 = 0.0, b21Du0 = 0.0, b22Du0 = 0.0; double b30Du0 = 0.0, b31Du0 = 0.0, b32Du0 = 0.0; double b00Du1 = 0.0, b01Du1 = 0.0, b02Du1 = 0.0; double b10Du1 = -1.0, b11Du1 = -1.0, b12Du1 = -1.0; double b20Du1 = 0.0, b21Du1 = 0.0, b22Du1 = 0.0; double b30Du1 = 0.0, b31Du1 = 0.0, b32Du1 = 0.0; double b00Du2 = 0.0, b01Du2 = 0.0, b02Du2 = 0.0; double b10Du2 = 0.0, b11Du2 = 0.0, b12Du2 = 0.0; double b20Du2 = -1.0, b21Du2 = -1.0, b22Du2 = -1.0; double b30Du2 = 0.0, b31Du2 = 0.0, b32Du2 = 0.0; double b00Du3 = 0.0, b01Du3 = 0.0, b02Du3 = 0.0; double b10Du3 = 0.0, b11Du3 = 0.0, b12Du3 = 0.0; double b20Du3 = 0.0, b21Du3 = 0.0, b22Du3 = 0.0; double b30Du3 = -1.0, b31Du3 = -1.0, b32Du3 = -1.0; double b00Dv0 = 1.0, b01Dv0 = 0.0, b02Dv0 = 0.0; double b10Dv0 = 0.0, b11Dv0 = 0.0, b12Dv0 = 0.0; double b20Dv0 = 0.0, b21Dv0 = 0.0, b22Dv0 = 0.0; double b30Dv0 = 0.0, b31Dv0 = 0.0, b32Dv0 = 0.0; double b00Dv1 = 0.0, b01Dv1 = 0.0, b02Dv1 = 0.0; double b10Dv1 = 1.0, b11Dv1 = 0.0, b12Dv1 = 0.0; double b20Dv1 = 0.0, b21Dv1 = 0.0, b22Dv1 = 0.0; double b30Dv1 = 0.0, b31Dv1 = 0.0, b32Dv1 = 0.0; double b00Dv2 = 0.0, b01Dv2 = 0.0, b02Dv2 = 0.0; double b10Dv2 = 0.0, b11Dv2 = 0.0, b12Dv2 = 0.0; double b20Dv2 = 1.0, b21Dv2 = 0.0, b22Dv2 = 0.0; double b30Dv2 = 0.0, b31Dv2 = 0.0, b32Dv2 = 0.0; double b00Dv3 = 0.0, b01Dv3 = 0.0, b02Dv3 = 0.0; double b10Dv3 = 0.0, b11Dv3 = 0.0, b12Dv3 = 0.0; double b20Dv3 = 0.0, b21Dv3 = 0.0, b22Dv3 = 0.0; double b30Dv3 = 1.0, b31Dv3 = 0.0, b32Dv3 = 0.0; double b00Dw0 = 0.0, b01Dw0 = 1.0, b02Dw0 = 0.0; double b10Dw0 = 0.0, b11Dw0 = 0.0, b12Dw0 = 0.0; double b20Dw0 = 0.0, b21Dw0 = 0.0, b22Dw0 = 0.0; double b30Dw0 = 0.0, b31Dw0 = 0.0, b32Dw0 = 0.0; double b00Dw1 = 0.0, b01Dw1 = 0.0, b02Dw1 = 0.0; double b10Dw1 = 0.0, b11Dw1 = 1.0, b12Dw1 = 0.0; double b20Dw1 = 0.0, b21Dw1 = 0.0, b22Dw1 = 0.0; double b30Dw1 = 0.0, b31Dw1 = 0.0, b32Dw1 = 0.0; double b00Dw2 = 0.0, b01Dw2 = 0.0, b02Dw2 = 0.0; double b10Dw2 = 0.0, b11Dw2 = 0.0, b12Dw2 = 0.0; double b20Dw2 = 0.0, b21Dw2 = 1.0, b22Dw2 = 0.0; double b30Dw2 = 0.0, b31Dw2 = 0.0, b32Dw2 = 0.0; double b00Dw3 = 0.0, b01Dw3 = 0.0, b02Dw3 = 0.0; double b10Dw3 = 0.0, b11Dw3 = 0.0, b12Dw3 = 0.0; double b20Dw3 = 0.0, b21Dw3 = 0.0, b22Dw3 = 0.0; double b30Dw3 = 0.0, b31Dw3 = 1.0, b32Dw3 = 0.0; double b00Dx0 = 0.0, b01Dx0 = 0.0, b02Dx0 = 1.0; double b10Dx0 = 0.0, b11Dx0 = 0.0, b12Dx0 = 0.0; double b20Dx0 = 0.0, b21Dx0 = 0.0, b22Dx0 = 0.0; double b30Dx0 = 0.0, b31Dx0 = 0.0, b32Dx0 = 0.0; double b00Dx1 = 0.0, b01Dx1 = 0.0, b02Dx1 = 0.0; double b10Dx1 = 0.0, b11Dx1 = 0.0, b12Dx1 = 1.0; double b20Dx1 = 0.0, b21Dx1 = 0.0, b22Dx1 = 0.0; double b30Dx1 = 0.0, b31Dx1 = 0.0, b32Dx1 = 0.0; double b00Dx2 = 0.0, b01Dx2 = 0.0, b02Dx2 = 0.0; double b10Dx2 = 0.0, b11Dx2 = 0.0, b12Dx2 = 0.0; double b20Dx2 = 0.0, b21Dx2 = 0.0, b22Dx2 = 1.0; double b30Dx2 = 0.0, b31Dx2 = 0.0, b32Dx2 = 0.0; double b00Dx3 = 0.0, b01Dx3 = 0.0, b02Dx3 = 0.0; double b10Dx3 = 0.0, b11Dx3 = 0.0, b12Dx3 = 0.0; double b20Dx3 = 0.0, b21Dx3 = 0.0, b22Dx3 = 0.0; double b30Dx3 = 0.0, b31Dx3 = 0.0, b32Dx3 = 1.0; double c00Du0 = 0.5 * (-b00Du0 + b01Du0 + b02Du0); double c01Du0 = 0.5 * ( b00Du0 - b01Du0 + b02Du0); double c02Du0 = 0.5 * ( b00Du0 + b01Du0 - b02Du0); double c10Du0 = 0.5 * (-b10Du0 + b11Du0 + b12Du0); double c11Du0 = 0.5 * ( b10Du0 - b11Du0 + b12Du0); double c12Du0 = 0.5 * ( b10Du0 + b11Du0 - b12Du0); double c20Du0 = 0.5 * (-b20Du0 + b21Du0 + b22Du0); double c21Du0 = 0.5 * ( b20Du0 - b21Du0 + b22Du0); double c22Du0 = 0.5 * ( b20Du0 + b21Du0 - b22Du0); double c30Du0 = 0.5 * (-b30Du0 + b31Du0 + b32Du0); double c31Du0 = 0.5 * ( b30Du0 - b31Du0 + b32Du0); double c32Du0 = 0.5 * ( b30Du0 + b31Du0 - b32Du0); double c00Du1 = 0.5 * (-b00Du1 + b01Du1 + b02Du1); double c01Du1 = 0.5 * ( b00Du1 - b01Du1 + b02Du1); double c02Du1 = 0.5 * ( b00Du1 + b01Du1 - b02Du1); double c10Du1 = 0.5 * (-b10Du1 + b11Du1 + b12Du1); double c11Du1 = 0.5 * ( b10Du1 - b11Du1 + b12Du1); double c12Du1 = 0.5 * ( b10Du1 + b11Du1 - b12Du1); double c20Du1 = 0.5 * (-b20Du1 + b21Du1 + b22Du1); double c21Du1 = 0.5 * ( b20Du1 - b21Du1 + b22Du1); double c22Du1 = 0.5 * ( b20Du1 + b21Du1 - b22Du1); double c30Du1 = 0.5 * (-b30Du1 + b31Du1 + b32Du1); double c31Du1 = 0.5 * ( b30Du1 - b31Du1 + b32Du1); double c32Du1 = 0.5 * ( b30Du1 + b31Du1 - b32Du1); double c00Du2 = 0.5 * (-b00Du2 + b01Du2 + b02Du2); double c01Du2 = 0.5 * ( b00Du2 - b01Du2 + b02Du2); double c02Du2 = 0.5 * ( b00Du2 + b01Du2 - b02Du2); double c10Du2 = 0.5 * (-b10Du2 + b11Du2 + b12Du2); double c11Du2 = 0.5 * ( b10Du2 - b11Du2 + b12Du2); double c12Du2 = 0.5 * ( b10Du2 + b11Du2 - b12Du2); double c20Du2 = 0.5 * (-b20Du2 + b21Du2 + b22Du2); double c21Du2 = 0.5 * ( b20Du2 - b21Du2 + b22Du2); double c22Du2 = 0.5 * ( b20Du2 + b21Du2 - b22Du2); double c30Du2 = 0.5 * (-b30Du2 + b31Du2 + b32Du2); double c31Du2 = 0.5 * ( b30Du2 - b31Du2 + b32Du2); double c32Du2 = 0.5 * ( b30Du2 + b31Du2 - b32Du2); double c00Du3 = 0.5 * (-b00Du3 + b01Du3 + b02Du3); double c01Du3 = 0.5 * ( b00Du3 - b01Du3 + b02Du3); double c02Du3 = 0.5 * ( b00Du3 + b01Du3 - b02Du3); double c10Du3 = 0.5 * (-b10Du3 + b11Du3 + b12Du3); double c11Du3 = 0.5 * ( b10Du3 - b11Du3 + b12Du3); double c12Du3 = 0.5 * ( b10Du3 + b11Du3 - b12Du3); double c20Du3 = 0.5 * (-b20Du3 + b21Du3 + b22Du3); double c21Du3 = 0.5 * ( b20Du3 - b21Du3 + b22Du3); double c22Du3 = 0.5 * ( b20Du3 + b21Du3 - b22Du3); double c30Du3 = 0.5 * (-b30Du3 + b31Du3 + b32Du3); double c31Du3 = 0.5 * ( b30Du3 - b31Du3 + b32Du3); double c32Du3 = 0.5 * ( b30Du3 + b31Du3 - b32Du3); double c00Dv0 = 0.5 * (-b00Dv0 + b01Dv0 + b02Dv0); double c01Dv0 = 0.5 * ( b00Dv0 - b01Dv0 + b02Dv0); double c02Dv0 = 0.5 * ( b00Dv0 + b01Dv0 - b02Dv0); double c10Dv0 = 0.5 * (-b10Dv0 + b11Dv0 + b12Dv0); double c11Dv0 = 0.5 * ( b10Dv0 - b11Dv0 + b12Dv0); double c12Dv0 = 0.5 * ( b10Dv0 + b11Dv0 - b12Dv0); double c20Dv0 = 0.5 * (-b20Dv0 + b21Dv0 + b22Dv0); double c21Dv0 = 0.5 * ( b20Dv0 - b21Dv0 + b22Dv0); double c22Dv0 = 0.5 * ( b20Dv0 + b21Dv0 - b22Dv0); double c30Dv0 = 0.5 * (-b30Dv0 + b31Dv0 + b32Dv0); double c31Dv0 = 0.5 * ( b30Dv0 - b31Dv0 + b32Dv0); double c32Dv0 = 0.5 * ( b30Dv0 + b31Dv0 - b32Dv0); double c00Dv1 = 0.5 * (-b00Dv1 + b01Dv1 + b02Dv1); double c01Dv1 = 0.5 * ( b00Dv1 - b01Dv1 + b02Dv1); double c02Dv1 = 0.5 * ( b00Dv1 + b01Dv1 - b02Dv1); double c10Dv1 = 0.5 * (-b10Dv1 + b11Dv1 + b12Dv1); double c11Dv1 = 0.5 * ( b10Dv1 - b11Dv1 + b12Dv1); double c12Dv1 = 0.5 * ( b10Dv1 + b11Dv1 - b12Dv1); double c20Dv1 = 0.5 * (-b20Dv1 + b21Dv1 + b22Dv1); double c21Dv1 = 0.5 * ( b20Dv1 - b21Dv1 + b22Dv1); double c22Dv1 = 0.5 * ( b20Dv1 + b21Dv1 - b22Dv1); double c30Dv1 = 0.5 * (-b30Dv1 + b31Dv1 + b32Dv1); double c31Dv1 = 0.5 * ( b30Dv1 - b31Dv1 + b32Dv1); double c32Dv1 = 0.5 * ( b30Dv1 + b31Dv1 - b32Dv1); double c00Dv2 = 0.5 * (-b00Dv2 + b01Dv2 + b02Dv2); double c01Dv2 = 0.5 * ( b00Dv2 - b01Dv2 + b02Dv2); double c02Dv2 = 0.5 * ( b00Dv2 + b01Dv2 - b02Dv2); double c10Dv2 = 0.5 * (-b10Dv2 + b11Dv2 + b12Dv2); double c11Dv2 = 0.5 * ( b10Dv2 - b11Dv2 + b12Dv2); double c12Dv2 = 0.5 * ( b10Dv2 + b11Dv2 - b12Dv2); double c20Dv2 = 0.5 * (-b20Dv2 + b21Dv2 + b22Dv2); double c21Dv2 = 0.5 * ( b20Dv2 - b21Dv2 + b22Dv2); double c22Dv2 = 0.5 * ( b20Dv2 + b21Dv2 - b22Dv2); double c30Dv2 = 0.5 * (-b30Dv2 + b31Dv2 + b32Dv2); double c31Dv2 = 0.5 * ( b30Dv2 - b31Dv2 + b32Dv2); double c32Dv2 = 0.5 * ( b30Dv2 + b31Dv2 - b32Dv2); double c00Dv3 = 0.5 * (-b00Dv3 + b01Dv3 + b02Dv3); double c01Dv3 = 0.5 * ( b00Dv3 - b01Dv3 + b02Dv3); double c02Dv3 = 0.5 * ( b00Dv3 + b01Dv3 - b02Dv3); double c10Dv3 = 0.5 * (-b10Dv3 + b11Dv3 + b12Dv3); double c11Dv3 = 0.5 * ( b10Dv3 - b11Dv3 + b12Dv3); double c12Dv3 = 0.5 * ( b10Dv3 + b11Dv3 - b12Dv3); double c20Dv3 = 0.5 * (-b20Dv3 + b21Dv3 + b22Dv3); double c21Dv3 = 0.5 * ( b20Dv3 - b21Dv3 + b22Dv3); double c22Dv3 = 0.5 * ( b20Dv3 + b21Dv3 - b22Dv3); double c30Dv3 = 0.5 * (-b30Dv3 + b31Dv3 + b32Dv3); double c31Dv3 = 0.5 * ( b30Dv3 - b31Dv3 + b32Dv3); double c32Dv3 = 0.5 * ( b30Dv3 + b31Dv3 - b32Dv3); double c00Dw0 = 0.5 * (-b00Dw0 + b01Dw0 + b02Dw0); double c01Dw0 = 0.5 * ( b00Dw0 - b01Dw0 + b02Dw0); double c02Dw0 = 0.5 * ( b00Dw0 + b01Dw0 - b02Dw0); double c10Dw0 = 0.5 * (-b10Dw0 + b11Dw0 + b12Dw0); double c11Dw0 = 0.5 * ( b10Dw0 - b11Dw0 + b12Dw0); double c12Dw0 = 0.5 * ( b10Dw0 + b11Dw0 - b12Dw0); double c20Dw0 = 0.5 * (-b20Dw0 + b21Dw0 + b22Dw0); double c21Dw0 = 0.5 * ( b20Dw0 - b21Dw0 + b22Dw0); double c22Dw0 = 0.5 * ( b20Dw0 + b21Dw0 - b22Dw0); double c30Dw0 = 0.5 * (-b30Dw0 + b31Dw0 + b32Dw0); double c31Dw0 = 0.5 * ( b30Dw0 - b31Dw0 + b32Dw0); double c32Dw0 = 0.5 * ( b30Dw0 + b31Dw0 - b32Dw0); double c00Dw1 = 0.5 * (-b00Dw1 + b01Dw1 + b02Dw1); double c01Dw1 = 0.5 * ( b00Dw1 - b01Dw1 + b02Dw1); double c02Dw1 = 0.5 * ( b00Dw1 + b01Dw1 - b02Dw1); double c10Dw1 = 0.5 * (-b10Dw1 + b11Dw1 + b12Dw1); double c11Dw1 = 0.5 * ( b10Dw1 - b11Dw1 + b12Dw1); double c12Dw1 = 0.5 * ( b10Dw1 + b11Dw1 - b12Dw1); double c20Dw1 = 0.5 * (-b20Dw1 + b21Dw1 + b22Dw1); double c21Dw1 = 0.5 * ( b20Dw1 - b21Dw1 + b22Dw1); double c22Dw1 = 0.5 * ( b20Dw1 + b21Dw1 - b22Dw1); double c30Dw1 = 0.5 * (-b30Dw1 + b31Dw1 + b32Dw1); double c31Dw1 = 0.5 * ( b30Dw1 - b31Dw1 + b32Dw1); double c32Dw1 = 0.5 * ( b30Dw1 + b31Dw1 - b32Dw1); double c00Dw2 = 0.5 * (-b00Dw2 + b01Dw2 + b02Dw2); double c01Dw2 = 0.5 * ( b00Dw2 - b01Dw2 + b02Dw2); double c02Dw2 = 0.5 * ( b00Dw2 + b01Dw2 - b02Dw2); double c10Dw2 = 0.5 * (-b10Dw2 + b11Dw2 + b12Dw2); double c11Dw2 = 0.5 * ( b10Dw2 - b11Dw2 + b12Dw2); double c12Dw2 = 0.5 * ( b10Dw2 + b11Dw2 - b12Dw2); double c20Dw2 = 0.5 * (-b20Dw2 + b21Dw2 + b22Dw2); double c21Dw2 = 0.5 * ( b20Dw2 - b21Dw2 + b22Dw2); double c22Dw2 = 0.5 * ( b20Dw2 + b21Dw2 - b22Dw2); double c30Dw2 = 0.5 * (-b30Dw2 + b31Dw2 + b32Dw2); double c31Dw2 = 0.5 * ( b30Dw2 - b31Dw2 + b32Dw2); double c32Dw2 = 0.5 * ( b30Dw2 + b31Dw2 - b32Dw2); double c00Dw3 = 0.5 * (-b00Dw3 + b01Dw3 + b02Dw3); double c01Dw3 = 0.5 * ( b00Dw3 - b01Dw3 + b02Dw3); double c02Dw3 = 0.5 * ( b00Dw3 + b01Dw3 - b02Dw3); double c10Dw3 = 0.5 * (-b10Dw3 + b11Dw3 + b12Dw3); double c11Dw3 = 0.5 * ( b10Dw3 - b11Dw3 + b12Dw3); double c12Dw3 = 0.5 * ( b10Dw3 + b11Dw3 - b12Dw3); double c20Dw3 = 0.5 * (-b20Dw3 + b21Dw3 + b22Dw3); double c21Dw3 = 0.5 * ( b20Dw3 - b21Dw3 + b22Dw3); double c22Dw3 = 0.5 * ( b20Dw3 + b21Dw3 - b22Dw3); double c30Dw3 = 0.5 * (-b30Dw3 + b31Dw3 + b32Dw3); double c31Dw3 = 0.5 * ( b30Dw3 - b31Dw3 + b32Dw3); double c32Dw3 = 0.5 * ( b30Dw3 + b31Dw3 - b32Dw3); double c00Dx0 = 0.5 * (-b00Dx0 + b01Dx0 + b02Dx0); double c01Dx0 = 0.5 * ( b00Dx0 - b01Dx0 + b02Dx0); double c02Dx0 = 0.5 * ( b00Dx0 + b01Dx0 - b02Dx0); double c10Dx0 = 0.5 * (-b10Dx0 + b11Dx0 + b12Dx0); double c11Dx0 = 0.5 * ( b10Dx0 - b11Dx0 + b12Dx0); double c12Dx0 = 0.5 * ( b10Dx0 + b11Dx0 - b12Dx0); double c20Dx0 = 0.5 * (-b20Dx0 + b21Dx0 + b22Dx0); double c21Dx0 = 0.5 * ( b20Dx0 - b21Dx0 + b22Dx0); double c22Dx0 = 0.5 * ( b20Dx0 + b21Dx0 - b22Dx0); double c30Dx0 = 0.5 * (-b30Dx0 + b31Dx0 + b32Dx0); double c31Dx0 = 0.5 * ( b30Dx0 - b31Dx0 + b32Dx0); double c32Dx0 = 0.5 * ( b30Dx0 + b31Dx0 - b32Dx0); double c00Dx1 = 0.5 * (-b00Dx1 + b01Dx1 + b02Dx1); double c01Dx1 = 0.5 * ( b00Dx1 - b01Dx1 + b02Dx1); double c02Dx1 = 0.5 * ( b00Dx1 + b01Dx1 - b02Dx1); double c10Dx1 = 0.5 * (-b10Dx1 + b11Dx1 + b12Dx1); double c11Dx1 = 0.5 * ( b10Dx1 - b11Dx1 + b12Dx1); double c12Dx1 = 0.5 * ( b10Dx1 + b11Dx1 - b12Dx1); double c20Dx1 = 0.5 * (-b20Dx1 + b21Dx1 + b22Dx1); double c21Dx1 = 0.5 * ( b20Dx1 - b21Dx1 + b22Dx1); double c22Dx1 = 0.5 * ( b20Dx1 + b21Dx1 - b22Dx1); double c30Dx1 = 0.5 * (-b30Dx1 + b31Dx1 + b32Dx1); double c31Dx1 = 0.5 * ( b30Dx1 - b31Dx1 + b32Dx1); double c32Dx1 = 0.5 * ( b30Dx1 + b31Dx1 - b32Dx1); double c00Dx2 = 0.5 * (-b00Dx2 + b01Dx2 + b02Dx2); double c01Dx2 = 0.5 * ( b00Dx2 - b01Dx2 + b02Dx2); double c02Dx2 = 0.5 * ( b00Dx2 + b01Dx2 - b02Dx2); double c10Dx2 = 0.5 * (-b10Dx2 + b11Dx2 + b12Dx2); double c11Dx2 = 0.5 * ( b10Dx2 - b11Dx2 + b12Dx2); double c12Dx2 = 0.5 * ( b10Dx2 + b11Dx2 - b12Dx2); double c20Dx2 = 0.5 * (-b20Dx2 + b21Dx2 + b22Dx2); double c21Dx2 = 0.5 * ( b20Dx2 - b21Dx2 + b22Dx2); double c22Dx2 = 0.5 * ( b20Dx2 + b21Dx2 - b22Dx2); double c30Dx2 = 0.5 * (-b30Dx2 + b31Dx2 + b32Dx2); double c31Dx2 = 0.5 * ( b30Dx2 - b31Dx2 + b32Dx2); double c32Dx2 = 0.5 * ( b30Dx2 + b31Dx2 - b32Dx2); double c00Dx3 = 0.5 * (-b00Dx3 + b01Dx3 + b02Dx3); double c01Dx3 = 0.5 * ( b00Dx3 - b01Dx3 + b02Dx3); double c02Dx3 = 0.5 * ( b00Dx3 + b01Dx3 - b02Dx3); double c10Dx3 = 0.5 * (-b10Dx3 + b11Dx3 + b12Dx3); double c11Dx3 = 0.5 * ( b10Dx3 - b11Dx3 + b12Dx3); double c12Dx3 = 0.5 * ( b10Dx3 + b11Dx3 - b12Dx3); double c20Dx3 = 0.5 * (-b20Dx3 + b21Dx3 + b22Dx3); double c21Dx3 = 0.5 * ( b20Dx3 - b21Dx3 + b22Dx3); double c22Dx3 = 0.5 * ( b20Dx3 + b21Dx3 - b22Dx3); double c30Dx3 = 0.5 * (-b30Dx3 + b31Dx3 + b32Dx3); double c31Dx3 = 0.5 * ( b30Dx3 - b31Dx3 + b32Dx3); double c32Dx3 = 0.5 * ( b30Dx3 + b31Dx3 - b32Dx3); double t00Du0 = 2.0 * (c00*c00Du0+c10*c10Du0+c20*c20Du0+c30*c30Du0); double t10Du0 = (c00*c01Du0+c01*c00Du0) + (c10*c11Du0+c11*c10Du0) + (c20*c21Du0+c21*c20Du0) + (c30*c31Du0+c31*c30Du0); double t11Du0 = 2.0 * (c01*c01Du0+c11*c11Du0+c21*c21Du0+c31*c31Du0); double t20Du0 = (c00*c02Du0+c02*c00Du0) + (c10*c12Du0+c12*c10Du0) + (c20*c22Du0+c22*c20Du0) + (c30*c32Du0+c32*c30Du0); double t21Du0 = (c01*c00Du0+c00*c01Du0) + (c11*c10Du0+c10*c11Du0) + (c21*c20Du0+c20*c21Du0) + (c31*c30Du0+c30*c31Du0); double t22Du0 = 2.0*(c02*c02Du0+c12*c12Du0+c22*c22Du0+c32*c32Du0); double t01Du0 = t10Du0; double t02Du0 = t20Du0; double t12Du0 = t21Du0; double t00Du1 = 2.0 * (c00*c00Du1+c10*c10Du1+c20*c20Du1+c30*c30Du1); double t10Du1 = (c00*c01Du1+c01*c00Du1) + (c10*c11Du1+c11*c10Du1) + (c20*c21Du1+c21*c20Du1) + (c30*c31Du1+c31*c30Du1); double t11Du1 = 2.0 * (c01*c01Du1+c11*c11Du1+c21*c21Du1+c31*c31Du1); double t20Du1 = (c00*c02Du1+c02*c00Du1) + (c10*c12Du1+c12*c10Du1) + (c20*c22Du1+c22*c20Du1) + (c30*c32Du1+c32*c30Du1); double t21Du1 = (c01*c00Du1+c00*c01Du1) + (c11*c10Du1+c10*c11Du1) + (c21*c20Du1+c20*c21Du1) + (c31*c30Du1+c30*c31Du1); double t22Du1 = 2.0*(c02*c02Du1+c12*c12Du1+c22*c22Du1+c32*c32Du1); double t01Du1 = t10Du1; double t02Du1 = t20Du1; double t12Du1 = t21Du1; double t00Du2 = 2.0 * (c00*c00Du2+c10*c10Du2+c20*c20Du2+c30*c30Du2); double t10Du2 = (c00*c01Du2+c01*c00Du2) + (c10*c11Du2+c11*c10Du2) + (c20*c21Du2+c21*c20Du2) + (c30*c31Du2+c31*c30Du2); double t11Du2 = 2.0 * (c01*c01Du2+c11*c11Du2+c21*c21Du2+c31*c31Du2); double t20Du2 = (c00*c02Du2+c02*c00Du2) + (c10*c12Du2+c12*c10Du2) + (c20*c22Du2+c22*c20Du2) + (c30*c32Du2+c32*c30Du2); double t21Du2 = (c01*c00Du2+c00*c01Du2) + (c11*c10Du2+c10*c11Du2) + (c21*c20Du2+c20*c21Du2) + (c31*c30Du2+c30*c31Du2); double t22Du2 = 2.0*(c02*c02Du2+c12*c12Du2+c22*c22Du2+c32*c32Du2); double t01Du2 = t10Du2; double t02Du2 = t20Du2; double t12Du2 = t21Du2; double t00Du3 = 2.0 * (c00*c00Du3+c10*c10Du3+c20*c20Du3+c30*c30Du3); double t10Du3 = (c00*c01Du3+c01*c00Du3) + (c10*c11Du3+c11*c10Du3) + (c20*c21Du3+c21*c20Du3) + (c30*c31Du3+c31*c30Du3); double t11Du3 = 2.0 * (c01*c01Du3+c11*c11Du3+c21*c21Du3+c31*c31Du3); double t20Du3 = (c00*c02Du3+c02*c00Du3) + (c10*c12Du3+c12*c10Du3) + (c20*c22Du3+c22*c20Du3) + (c30*c32Du3+c32*c30Du3); double t21Du3 = (c01*c00Du3+c00*c01Du3) + (c11*c10Du3+c10*c11Du3) + (c21*c20Du3+c20*c21Du3) + (c31*c30Du3+c30*c31Du3); double t22Du3 = 2.0*(c02*c02Du3+c12*c12Du3+c22*c22Du3+c32*c32Du3); double t01Du3 = t10Du3; double t02Du3 = t20Du3; double t12Du3 = t21Du3; double t00Dv0 = 2.0 * (c00*c00Dv0+c10*c10Dv0+c20*c20Dv0+c30*c30Dv0); double t10Dv0 = (c00*c01Dv0+c01*c00Dv0) + (c10*c11Dv0+c11*c10Dv0) + (c20*c21Dv0+c21*c20Dv0) + (c30*c31Dv0+c31*c30Dv0); double t11Dv0 = 2.0 * (c01*c01Dv0+c11*c11Dv0+c21*c21Dv0+c31*c31Dv0); double t20Dv0 = (c00*c02Dv0+c02*c00Dv0) + (c10*c12Dv0+c12*c10Dv0) + (c20*c22Dv0+c22*c20Dv0) + (c30*c32Dv0+c32*c30Dv0); double t21Dv0 = (c01*c00Dv0+c00*c01Dv0) + (c11*c10Dv0+c10*c11Dv0) + (c21*c20Dv0+c20*c21Dv0) + (c31*c30Dv0+c30*c31Dv0); double t22Dv0 = 2.0*(c02*c02Dv0+c12*c12Dv0+c22*c22Dv0+c32*c32Dv0); double t01Dv0 = t10Dv0; double t02Dv0 = t20Dv0; double t12Dv0 = t21Dv0; double t00Dv1 = 2.0 * (c00*c00Dv1+c10*c10Dv1+c20*c20Dv1+c30*c30Dv1); double t10Dv1 = (c00*c01Dv1+c01*c00Dv1) + (c10*c11Dv1+c11*c10Dv1) + (c20*c21Dv1+c21*c20Dv1) + (c30*c31Dv1+c31*c30Dv1); double t11Dv1 = 2.0 * (c01*c01Dv1+c11*c11Dv1+c21*c21Dv1+c31*c31Dv1); double t20Dv1 = (c00*c02Dv1+c02*c00Dv1) + (c10*c12Dv1+c12*c10Dv1) + (c20*c22Dv1+c22*c20Dv1) + (c30*c32Dv1+c32*c30Dv1); double t21Dv1 = (c01*c00Dv1+c00*c01Dv1) + (c11*c10Dv1+c10*c11Dv1) + (c21*c20Dv1+c20*c21Dv1) + (c31*c30Dv1+c30*c31Dv1); double t22Dv1 = 2.0*(c02*c02Dv1+c12*c12Dv1+c22*c22Dv1+c32*c32Dv1); double t01Dv1 = t10Dv1; double t02Dv1 = t20Dv1; double t12Dv1 = t21Dv1; double t00Dv2 = 2.0 * (c00*c00Dv2+c10*c10Dv2+c20*c20Dv2+c30*c30Dv2); double t10Dv2 = (c00*c01Dv2+c01*c00Dv2) + (c10*c11Dv2+c11*c10Dv2) + (c20*c21Dv2+c21*c20Dv2) + (c30*c31Dv2+c31*c30Dv2); double t11Dv2 = 2.0 * (c01*c01Dv2+c11*c11Dv2+c21*c21Dv2+c31*c31Dv2); double t20Dv2 = (c00*c02Dv2+c02*c00Dv2) + (c10*c12Dv2+c12*c10Dv2) + (c20*c22Dv2+c22*c20Dv2) + (c30*c32Dv2+c32*c30Dv2); double t21Dv2 = (c01*c00Dv2+c00*c01Dv2) + (c11*c10Dv2+c10*c11Dv2) + (c21*c20Dv2+c20*c21Dv2) + (c31*c30Dv2+c30*c31Dv2); double t22Dv2 = 2.0*(c02*c02Dv2+c12*c12Dv2+c22*c22Dv2+c32*c32Dv2); double t01Dv2 = t10Dv2; double t02Dv2 = t20Dv2; double t12Dv2 = t21Dv2; double t00Dv3 = 2.0 * (c00*c00Dv3+c10*c10Dv3+c20*c20Dv3+c30*c30Dv3); double t10Dv3 = (c00*c01Dv3+c01*c00Dv3) + (c10*c11Dv3+c11*c10Dv3) + (c20*c21Dv3+c21*c20Dv3) + (c30*c31Dv3+c31*c30Dv3); double t11Dv3 = 2.0 * (c01*c01Dv3+c11*c11Dv3+c21*c21Dv3+c31*c31Dv3); double t20Dv3 = (c00*c02Dv3+c02*c00Dv3) + (c10*c12Dv3+c12*c10Dv3) + (c20*c22Dv3+c22*c20Dv3) + (c30*c32Dv3+c32*c30Dv3); double t21Dv3 = (c01*c00Dv3+c00*c01Dv3) + (c11*c10Dv3+c10*c11Dv3) + (c21*c20Dv3+c20*c21Dv3) + (c31*c30Dv3+c30*c31Dv3); double t22Dv3 = 2.0*(c02*c02Dv3+c12*c12Dv3+c22*c22Dv3+c32*c32Dv3); double t01Dv3 = t10Dv3; double t02Dv3 = t20Dv3; double t12Dv3 = t21Dv3; double t00Dw0 = 2.0 * (c00*c00Dw0+c10*c10Dw0+c20*c20Dw0+c30*c30Dw0); double t10Dw0 = (c00*c01Dw0+c01*c00Dw0) + (c10*c11Dw0+c11*c10Dw0) + (c20*c21Dw0+c21*c20Dw0) + (c30*c31Dw0+c31*c30Dw0); double t11Dw0 = 2.0 * (c01*c01Dw0+c11*c11Dw0+c21*c21Dw0+c31*c31Dw0); double t20Dw0 = (c00*c02Dw0+c02*c00Dw0) + (c10*c12Dw0+c12*c10Dw0) + (c20*c22Dw0+c22*c20Dw0) + (c30*c32Dw0+c32*c30Dw0); double t21Dw0 = (c01*c00Dw0+c00*c01Dw0) + (c11*c10Dw0+c10*c11Dw0) + (c21*c20Dw0+c20*c21Dw0) + (c31*c30Dw0+c30*c31Dw0); double t22Dw0 = 2.0*(c02*c02Dw0+c12*c12Dw0+c22*c22Dw0+c32*c32Dw0); double t01Dw0 = t10Dw0; double t02Dw0 = t20Dw0; double t12Dw0 = t21Dw0; double t00Dw1 = 2.0 * (c00*c00Dw1+c10*c10Dw1+c20*c20Dw1+c30*c30Dw1); double t10Dw1 = (c00*c01Dw1+c01*c00Dw1) + (c10*c11Dw1+c11*c10Dw1) + (c20*c21Dw1+c21*c20Dw1) + (c30*c31Dw1+c31*c30Dw1); double t11Dw1 = 2.0 * (c01*c01Dw1+c11*c11Dw1+c21*c21Dw1+c31*c31Dw1); double t20Dw1 = (c00*c02Dw1+c02*c00Dw1) + (c10*c12Dw1+c12*c10Dw1) + (c20*c22Dw1+c22*c20Dw1) + (c30*c32Dw1+c32*c30Dw1); double t21Dw1 = (c01*c00Dw1+c00*c01Dw1) + (c11*c10Dw1+c10*c11Dw1) + (c21*c20Dw1+c20*c21Dw1) + (c31*c30Dw1+c30*c31Dw1); double t22Dw1 = 2.0*(c02*c02Dw1+c12*c12Dw1+c22*c22Dw1+c32*c32Dw1); double t01Dw1 = t10Dw1; double t02Dw1 = t20Dw1; double t12Dw1 = t21Dw1; double t00Dw2 = 2.0 * (c00*c00Dw2+c10*c10Dw2+c20*c20Dw2+c30*c30Dw2); double t10Dw2 = (c00*c01Dw2+c01*c00Dw2) + (c10*c11Dw2+c11*c10Dw2) + (c20*c21Dw2+c21*c20Dw2) + (c30*c31Dw2+c31*c30Dw2); double t11Dw2 = 2.0 * (c01*c01Dw2+c11*c11Dw2+c21*c21Dw2+c31*c31Dw2); double t20Dw2 = (c00*c02Dw2+c02*c00Dw2) + (c10*c12Dw2+c12*c10Dw2) + (c20*c22Dw2+c22*c20Dw2) + (c30*c32Dw2+c32*c30Dw2); double t21Dw2 = (c01*c00Dw2+c00*c01Dw2) + (c11*c10Dw2+c10*c11Dw2) + (c21*c20Dw2+c20*c21Dw2) + (c31*c30Dw2+c30*c31Dw2); double t22Dw2 = 2.0*(c02*c02Dw2+c12*c12Dw2+c22*c22Dw2+c32*c32Dw2); double t01Dw2 = t10Dw2; double t02Dw2 = t20Dw2; double t12Dw2 = t21Dw2; double t00Dw3 = 2.0 * (c00*c00Dw3+c10*c10Dw3+c20*c20Dw3+c30*c30Dw3); double t10Dw3 = (c00*c01Dw3+c01*c00Dw3) + (c10*c11Dw3+c11*c10Dw3) + (c20*c21Dw3+c21*c20Dw3) + (c30*c31Dw3+c31*c30Dw3); double t11Dw3 = 2.0 * (c01*c01Dw3+c11*c11Dw3+c21*c21Dw3+c31*c31Dw3); double t20Dw3 = (c00*c02Dw3+c02*c00Dw3) + (c10*c12Dw3+c12*c10Dw3) + (c20*c22Dw3+c22*c20Dw3) + (c30*c32Dw3+c32*c30Dw3); double t21Dw3 = (c01*c00Dw3+c00*c01Dw3) + (c11*c10Dw3+c10*c11Dw3) + (c21*c20Dw3+c20*c21Dw3) + (c31*c30Dw3+c30*c31Dw3); double t22Dw3 = 2.0*(c02*c02Dw3+c12*c12Dw3+c22*c22Dw3+c32*c32Dw3); double t01Dw3 = t10Dw3; double t02Dw3 = t20Dw3; double t12Dw3 = t21Dw3; double t00Dx0 = 2.0 * (c00*c00Dx0+c10*c10Dx0+c20*c20Dx0+c30*c30Dx0); double t10Dx0 = (c00*c01Dx0+c01*c00Dx0) + (c10*c11Dx0+c11*c10Dx0) + (c20*c21Dx0+c21*c20Dx0) + (c30*c31Dx0+c31*c30Dx0); double t11Dx0 = 2.0 * (c01*c01Dx0+c11*c11Dx0+c21*c21Dx0+c31*c31Dx0); double t20Dx0 = (c00*c02Dx0+c02*c00Dx0) + (c10*c12Dx0+c12*c10Dx0) + (c20*c22Dx0+c22*c20Dx0) + (c30*c32Dx0+c32*c30Dx0); double t21Dx0 = (c01*c00Dx0+c00*c01Dx0) + (c11*c10Dx0+c10*c11Dx0) + (c21*c20Dx0+c20*c21Dx0) + (c31*c30Dx0+c30*c31Dx0); double t22Dx0 = 2.0*(c02*c02Dx0+c12*c12Dx0+c22*c22Dx0+c32*c32Dx0); double t01Dx0 = t10Dx0; double t02Dx0 = t20Dx0; double t12Dx0 = t21Dx0; double t00Dx1 = 2.0 * (c00*c00Dx1+c10*c10Dx1+c20*c20Dx1+c30*c30Dx1); double t10Dx1 = (c00*c01Dx1+c01*c00Dx1) + (c10*c11Dx1+c11*c10Dx1) + (c20*c21Dx1+c21*c20Dx1) + (c30*c31Dx1+c31*c30Dx1); double t11Dx1 = 2.0 * (c01*c01Dx1+c11*c11Dx1+c21*c21Dx1+c31*c31Dx1); double t20Dx1 = (c00*c02Dx1+c02*c00Dx1) + (c10*c12Dx1+c12*c10Dx1) + (c20*c22Dx1+c22*c20Dx1) + (c30*c32Dx1+c32*c30Dx1); double t21Dx1 = (c01*c00Dx1+c00*c01Dx1) + (c11*c10Dx1+c10*c11Dx1) + (c21*c20Dx1+c20*c21Dx1) + (c31*c30Dx1+c30*c31Dx1); double t22Dx1 = 2.0*(c02*c02Dx1+c12*c12Dx1+c22*c22Dx1+c32*c32Dx1); double t01Dx1 = t10Dx1; double t02Dx1 = t20Dx1; double t12Dx1 = t21Dx1; double t00Dx2 = 2.0 * (c00*c00Dx2+c10*c10Dx2+c20*c20Dx2+c30*c30Dx2); double t10Dx2 = (c00*c01Dx2+c01*c00Dx2) + (c10*c11Dx2+c11*c10Dx2) + (c20*c21Dx2+c21*c20Dx2) + (c30*c31Dx2+c31*c30Dx2); double t11Dx2 = 2.0 * (c01*c01Dx2+c11*c11Dx2+c21*c21Dx2+c31*c31Dx2); double t20Dx2 = (c00*c02Dx2+c02*c00Dx2) + (c10*c12Dx2+c12*c10Dx2) + (c20*c22Dx2+c22*c20Dx2) + (c30*c32Dx2+c32*c30Dx2); double t21Dx2 = (c01*c00Dx2+c00*c01Dx2) + (c11*c10Dx2+c10*c11Dx2) + (c21*c20Dx2+c20*c21Dx2) + (c31*c30Dx2+c30*c31Dx2); double t22Dx2 = 2.0*(c02*c02Dx2+c12*c12Dx2+c22*c22Dx2+c32*c32Dx2); double t01Dx2 = t10Dx2; double t02Dx2 = t20Dx2; double t12Dx2 = t21Dx2; double t00Dx3 = 2.0 * (c00*c00Dx3+c10*c10Dx3+c20*c20Dx3+c30*c30Dx3); double t10Dx3 = (c00*c01Dx3+c01*c00Dx3) + (c10*c11Dx3+c11*c10Dx3) + (c20*c21Dx3+c21*c20Dx3) + (c30*c31Dx3+c31*c30Dx3); double t11Dx3 = 2.0 * (c01*c01Dx3+c11*c11Dx3+c21*c21Dx3+c31*c31Dx3); double t20Dx3 = (c00*c02Dx3+c02*c00Dx3) + (c10*c12Dx3+c12*c10Dx3) + (c20*c22Dx3+c22*c20Dx3) + (c30*c32Dx3+c32*c30Dx3); double t21Dx3 = (c01*c00Dx3+c00*c01Dx3) + (c11*c10Dx3+c10*c11Dx3) + (c21*c20Dx3+c20*c21Dx3) + (c31*c30Dx3+c30*c31Dx3); double t22Dx3 = 2.0*(c02*c02Dx3+c12*c12Dx3+c22*c22Dx3+c32*c32Dx3); double t01Dx3 = t10Dx3; double t02Dx3 = t20Dx3; double t12Dx3 = t21Dx3; double T11Du0 = (t11*t22Du0+t22*t11Du0) - (t12*t12Du0+t12*t12Du0); double T22Du0 = (t00*t22Du0+t22*t00Du0) - (t02*t02Du0+t02*t02Du0); double T33Du0 = (t00*t11Du0+t11*t00Du0) - (t01*t01Du0+t01*t01Du0); double T13Du0 = (t01*t12Du0+t12*t01Du0) - (t11*t02Du0+t02*t11Du0); double T12Du0 = (t01*t22Du0+t22*t01Du0) - (t12*t02Du0+t02*t12Du0); double T11Du1 = (t11*t22Du1+t22*t11Du1) - (t12*t12Du1+t12*t12Du1); double T22Du1 = (t00*t22Du1+t22*t00Du1) - (t02*t02Du1+t02*t02Du1); double T33Du1 = (t00*t11Du1+t11*t00Du1) - (t01*t01Du1+t01*t01Du1); double T13Du1 = (t01*t12Du1+t12*t01Du1) - (t11*t02Du1+t02*t11Du1); double T12Du1 = (t01*t22Du1+t22*t01Du1) - (t12*t02Du1+t02*t12Du1); double T11Du2 = (t11*t22Du2+t22*t11Du2) - (t12*t12Du2+t12*t12Du2); double T22Du2 = (t00*t22Du2+t22*t00Du2) - (t02*t02Du2+t02*t02Du2); double T33Du2 = (t00*t11Du2+t11*t00Du2) - (t01*t01Du2+t01*t01Du2); double T13Du2 = (t01*t12Du2+t12*t01Du2) - (t11*t02Du2+t02*t11Du2); double T12Du2 = (t01*t22Du2+t22*t01Du2) - (t12*t02Du2+t02*t12Du2); double T11Du3 = (t11*t22Du3+t22*t11Du3) - (t12*t12Du3+t12*t12Du3); double T22Du3 = (t00*t22Du3+t22*t00Du3) - (t02*t02Du3+t02*t02Du3); double T33Du3 = (t00*t11Du3+t11*t00Du3) - (t01*t01Du3+t01*t01Du3); double T13Du3 = (t01*t12Du3+t12*t01Du3) - (t11*t02Du3+t02*t11Du3); double T12Du3 = (t01*t22Du3+t22*t01Du3) - (t12*t02Du3+t02*t12Du3); double T11Dv0 = (t11*t22Dv0+t22*t11Dv0) - (t12*t12Dv0+t12*t12Dv0); double T22Dv0 = (t00*t22Dv0+t22*t00Dv0) - (t02*t02Dv0+t02*t02Dv0); double T33Dv0 = (t00*t11Dv0+t11*t00Dv0) - (t01*t01Dv0+t01*t01Dv0); double T13Dv0 = (t01*t12Dv0+t12*t01Dv0) - (t11*t02Dv0+t02*t11Dv0); double T12Dv0 = (t01*t22Dv0+t22*t01Dv0) - (t12*t02Dv0+t02*t12Dv0); double T11Dv1 = (t11*t22Dv1+t22*t11Dv1) - (t12*t12Dv1+t12*t12Dv1); double T22Dv1 = (t00*t22Dv1+t22*t00Dv1) - (t02*t02Dv1+t02*t02Dv1); double T33Dv1 = (t00*t11Dv1+t11*t00Dv1) - (t01*t01Dv1+t01*t01Dv1); double T13Dv1 = (t01*t12Dv1+t12*t01Dv1) - (t11*t02Dv1+t02*t11Dv1); double T12Dv1 = (t01*t22Dv1+t22*t01Dv1) - (t12*t02Dv1+t02*t12Dv1); double T11Dv2 = (t11*t22Dv2+t22*t11Dv2) - (t12*t12Dv2+t12*t12Dv2); double T22Dv2 = (t00*t22Dv2+t22*t00Dv2) - (t02*t02Dv2+t02*t02Dv2); double T33Dv2 = (t00*t11Dv2+t11*t00Dv2) - (t01*t01Dv2+t01*t01Dv2); double T13Dv2 = (t01*t12Dv2+t12*t01Dv2) - (t11*t02Dv2+t02*t11Dv2); double T12Dv2 = (t01*t22Dv2+t22*t01Dv2) - (t12*t02Dv2+t02*t12Dv2); double T11Dv3 = (t11*t22Dv3+t22*t11Dv3) - (t12*t12Dv3+t12*t12Dv3); double T22Dv3 = (t00*t22Dv3+t22*t00Dv3) - (t02*t02Dv3+t02*t02Dv3); double T33Dv3 = (t00*t11Dv3+t11*t00Dv3) - (t01*t01Dv3+t01*t01Dv3); double T13Dv3 = (t01*t12Dv3+t12*t01Dv3) - (t11*t02Dv3+t02*t11Dv3); double T12Dv3 = (t01*t22Dv3+t22*t01Dv3) - (t12*t02Dv3+t02*t12Dv3); double T11Dw0 = (t11*t22Dw0+t22*t11Dw0) - (t12*t12Dw0+t12*t12Dw0); double T22Dw0 = (t00*t22Dw0+t22*t00Dw0) - (t02*t02Dw0+t02*t02Dw0); double T33Dw0 = (t00*t11Dw0+t11*t00Dw0) - (t01*t01Dw0+t01*t01Dw0); double T13Dw0 = (t01*t12Dw0+t12*t01Dw0) - (t11*t02Dw0+t02*t11Dw0); double T12Dw0 = (t01*t22Dw0+t22*t01Dw0) - (t12*t02Dw0+t02*t12Dw0); double T11Dw1 = (t11*t22Dw1+t22*t11Dw1) - (t12*t12Dw1+t12*t12Dw1); double T22Dw1 = (t00*t22Dw1+t22*t00Dw1) - (t02*t02Dw1+t02*t02Dw1); double T33Dw1 = (t00*t11Dw1+t11*t00Dw1) - (t01*t01Dw1+t01*t01Dw1); double T13Dw1 = (t01*t12Dw1+t12*t01Dw1) - (t11*t02Dw1+t02*t11Dw1); double T12Dw1 = (t01*t22Dw1+t22*t01Dw1) - (t12*t02Dw1+t02*t12Dw1); double T11Dw2 = (t11*t22Dw2+t22*t11Dw2) - (t12*t12Dw2+t12*t12Dw2); double T22Dw2 = (t00*t22Dw2+t22*t00Dw2) - (t02*t02Dw2+t02*t02Dw2); double T33Dw2 = (t00*t11Dw2+t11*t00Dw2) - (t01*t01Dw2+t01*t01Dw2); double T13Dw2 = (t01*t12Dw2+t12*t01Dw2) - (t11*t02Dw2+t02*t11Dw2); double T12Dw2 = (t01*t22Dw2+t22*t01Dw2) - (t12*t02Dw2+t02*t12Dw2); double T11Dw3 = (t11*t22Dw3+t22*t11Dw3) - (t12*t12Dw3+t12*t12Dw3); double T22Dw3 = (t00*t22Dw3+t22*t00Dw3) - (t02*t02Dw3+t02*t02Dw3); double T33Dw3 = (t00*t11Dw3+t11*t00Dw3) - (t01*t01Dw3+t01*t01Dw3); double T13Dw3 = (t01*t12Dw3+t12*t01Dw3) - (t11*t02Dw3+t02*t11Dw3); double T12Dw3 = (t01*t22Dw3+t22*t01Dw3) - (t12*t02Dw3+t02*t12Dw3); double T11Dx0 = (t11*t22Dx0+t22*t11Dx0) - (t12*t12Dx0+t12*t12Dx0); double T22Dx0 = (t00*t22Dx0+t22*t00Dx0) - (t02*t02Dx0+t02*t02Dx0); double T33Dx0 = (t00*t11Dx0+t11*t00Dx0) - (t01*t01Dx0+t01*t01Dx0); double T13Dx0 = (t01*t12Dx0+t12*t01Dx0) - (t11*t02Dx0+t02*t11Dx0); double T12Dx0 = (t01*t22Dx0+t22*t01Dx0) - (t12*t02Dx0+t02*t12Dx0); double T11Dx1 = (t11*t22Dx1+t22*t11Dx1) - (t12*t12Dx1+t12*t12Dx1); double T22Dx1 = (t00*t22Dx1+t22*t00Dx1) - (t02*t02Dx1+t02*t02Dx1); double T33Dx1 = (t00*t11Dx1+t11*t00Dx1) - (t01*t01Dx1+t01*t01Dx1); double T13Dx1 = (t01*t12Dx1+t12*t01Dx1) - (t11*t02Dx1+t02*t11Dx1); double T12Dx1 = (t01*t22Dx1+t22*t01Dx1) - (t12*t02Dx1+t02*t12Dx1); double T11Dx2 = (t11*t22Dx2+t22*t11Dx2) - (t12*t12Dx2+t12*t12Dx2); double T22Dx2 = (t00*t22Dx2+t22*t00Dx2) - (t02*t02Dx2+t02*t02Dx2); double T33Dx2 = (t00*t11Dx2+t11*t00Dx2) - (t01*t01Dx2+t01*t01Dx2); double T13Dx2 = (t01*t12Dx2+t12*t01Dx2) - (t11*t02Dx2+t02*t11Dx2); double T12Dx2 = (t01*t22Dx2+t22*t01Dx2) - (t12*t02Dx2+t02*t12Dx2); double T11Dx3 = (t11*t22Dx3+t22*t11Dx3) - (t12*t12Dx3+t12*t12Dx3); double T22Dx3 = (t00*t22Dx3+t22*t00Dx3) - (t02*t02Dx3+t02*t02Dx3); double T33Dx3 = (t00*t11Dx3+t11*t00Dx3) - (t01*t01Dx3+t01*t01Dx3); double T13Dx3 = (t01*t12Dx3+t12*t01Dx3) - (t11*t02Dx3+t02*t11Dx3); double T12Dx3 = (t01*t22Dx3+t22*t01Dx3) - (t12*t02Dx3+t02*t12Dx3); double delDu0 = (t00*T11Du0+t00Du0*T11) - (t01*T12Du0+t01Du0*T12) + (t02*T13Du0+t02Du0*T13); double gamDu0 = t00Du0 + t11Du0 + t22Du0; double sigDu0 = T11Du0 + T22Du0 + T33Du0; double delDu1 = (t00*T11Du1+t00Du1*T11) - (t01*T12Du1+t01Du1*T12) + (t02*T13Du1+t02Du1*T13); double gamDu1 = t00Du1 + t11Du1 + t22Du1; double sigDu1 = T11Du1 + T22Du1 + T33Du1; double delDu2 = (t00*T11Du2+t00Du2*T11) - (t01*T12Du2+t01Du2*T12) + (t02*T13Du2+t02Du2*T13); double gamDu2 = t00Du2 + t11Du2 + t22Du2; double sigDu2 = T11Du2 + T22Du2 + T33Du2; double delDu3 = (t00*T11Du3+t00Du3*T11) - (t01*T12Du3+t01Du3*T12) + (t02*T13Du3+t02Du3*T13); double gamDu3 = t00Du3 + t11Du3 + t22Du3; double sigDu3 = T11Du3 + T22Du3 + T33Du3; double delDv0 = (t00*T11Dv0+t00Dv0*T11) - (t01*T12Dv0+t01Dv0*T12) + (t02*T13Dv0+t02Dv0*T13); double gamDv0 = t00Dv0 + t11Dv0 + t22Dv0; double sigDv0 = T11Dv0 + T22Dv0 + T33Dv0; double delDv1 = (t00*T11Dv1+t00Dv1*T11) - (t01*T12Dv1+t01Dv1*T12) + (t02*T13Dv1+t02Dv1*T13); double gamDv1 = t00Dv1 + t11Dv1 + t22Dv1; double sigDv1 = T11Dv1 + T22Dv1 + T33Dv1; double delDv2 = (t00*T11Dv2+t00Dv2*T11) - (t01*T12Dv2+t01Dv2*T12) + (t02*T13Dv2+t02Dv2*T13); double gamDv2 = t00Dv2 + t11Dv2 + t22Dv2; double sigDv2 = T11Dv2 + T22Dv2 + T33Dv2; double delDv3 = (t00*T11Dv3+t00Dv3*T11) - (t01*T12Dv3+t01Dv3*T12) + (t02*T13Dv3+t02Dv3*T13); double gamDv3 = t00Dv3 + t11Dv3 + t22Dv3; double sigDv3 = T11Dv3 + T22Dv3 + T33Dv3; double delDw0 = (t00*T11Dw0+t00Dw0*T11) - (t01*T12Dw0+t01Dw0*T12) + (t02*T13Dw0+t02Dw0*T13); double gamDw0 = t00Dw0 + t11Dw0 + t22Dw0; double sigDw0 = T11Dw0 + T22Dw0 + T33Dw0; double delDw1 = (t00*T11Dw1+t00Dw1*T11) - (t01*T12Dw1+t01Dw1*T12) + (t02*T13Dw1+t02Dw1*T13); double gamDw1 = t00Dw1 + t11Dw1 + t22Dw1; double sigDw1 = T11Dw1 + T22Dw1 + T33Dw1; double delDw2 = (t00*T11Dw2+t00Dw2*T11) - (t01*T12Dw2+t01Dw2*T12) + (t02*T13Dw2+t02Dw2*T13); double gamDw2 = t00Dw2 + t11Dw2 + t22Dw2; double sigDw2 = T11Dw2 + T22Dw2 + T33Dw2; double delDw3 = (t00*T11Dw3+t00Dw3*T11) - (t01*T12Dw3+t01Dw3*T12) + (t02*T13Dw3+t02Dw3*T13); double gamDw3 = t00Dw3 + t11Dw3 + t22Dw3; double sigDw3 = T11Dw3 + T22Dw3 + T33Dw3; double delDx0 = (t00*T11Dx0+t00Dx0*T11) - (t01*T12Dx0+t01Dx0*T12) + (t02*T13Dx0+t02Dx0*T13); double gamDx0 = t00Dx0 + t11Dx0 + t22Dx0; double sigDx0 = T11Dx0 + T22Dx0 + T33Dx0; double delDx1 = (t00*T11Dx1+t00Dx1*T11) - (t01*T12Dx1+t01Dx1*T12) + (t02*T13Dx1+t02Dx1*T13); double gamDx1 = t00Dx1 + t11Dx1 + t22Dx1; double sigDx1 = T11Dx1 + T22Dx1 + T33Dx1; double delDx2 = (t00*T11Dx2+t00Dx2*T11) - (t01*T12Dx2+t01Dx2*T12) + (t02*T13Dx2+t02Dx2*T13); double gamDx2 = t00Dx2 + t11Dx2 + t22Dx2; double sigDx2 = T11Dx2 + T22Dx2 + T33Dx2; double delDx3 = (t00*T11Dx3+t00Dx3*T11) - (t01*T12Dx3+t01Dx3*T12) + (t02*T13Dx3+t02Dx3*T13); double gamDx3 = t00Dx3 + t11Dx3 + t22Dx3; double sigDx3 = T11Dx3 + T22Dx3 + T33Dx3; double te1Du0 = alpha/32.0*(2.0*Delta*delDu0-2.0*Del_3*delDu0); double te2Du0 = beta/6.0*(2.0*Sigma*gamDu0-3.0 *sigDu0); double te1Dv0 = alpha/32.0*(2.0*Delta*delDv0-2.0*Del_3*delDv0); double te2Dv0 = beta/6.0*(2.0*Sigma*gamDv0-3.0 *sigDv0); double te1Dw0 = alpha/32.0*(2.0*Delta*delDw0-2.0*Del_3*delDw0); double te2Dw0 = beta/6.0*(2.0*Sigma*gamDw0-3.0 *sigDw0); double te1Dx0 = alpha/32.0*(2.0*Delta*delDx0-2.0*Del_3*delDx0); double te2Dx0 = beta/6.0*(2.0*Sigma*gamDx0-3.0 *sigDx0); double te1Du1 = alpha/32.0*(2.0*Delta*delDu1-2.0*Del_3*delDu1); double te2Du1 = beta/6.0*(2.0*Sigma*gamDu1-3.0 *sigDu1); double te1Dv1 = alpha/32.0*(2.0*Delta*delDv1-2.0*Del_3*delDv1); double te2Dv1 = beta/6.0*(2.0*Sigma*gamDv1-3.0 *sigDv1); double te1Dw1 = alpha/32.0*(2.0*Delta*delDw1-2.0*Del_3*delDw1); double te2Dw1 = beta/6.0*(2.0*Sigma*gamDw1-3.0 *sigDw1); double te1Dx1 = alpha/32.0*(2.0*Delta*delDx1-2.0*Del_3*delDx1); double te2Dx1 = beta/6.0*(2.0*Sigma*gamDx1-3.0 *sigDx1); double te1Du2 = alpha/32.0*(2.0*Delta*delDu2-2.0*Del_3*delDu2); double te2Du2 = beta/6.0*(2.0*Sigma*gamDu2-3.0 *sigDu2); double te1Dv2 = alpha/32.0*(2.0*Delta*delDv2-2.0*Del_3*delDv2); double te2Dv2 = beta/6.0*(2.0*Sigma*gamDv2-3.0 *sigDv2); double te1Dw2 = alpha/32.0*(2.0*Delta*delDw2-2.0*Del_3*delDw2); double te2Dw2 = beta/6.0*(2.0*Sigma*gamDw2-3.0 *sigDw2); double te1Dx2 = alpha/32.0*(2.0*Delta*delDx2-2.0*Del_3*delDx2); double te2Dx2 = beta/6.0*(2.0*Sigma*gamDx2-3.0 *sigDx2); double te1Du3 = alpha/32.0*(2.0*Delta*delDu3-2.0*Del_3*delDu3); double te2Du3 = beta/6.0*(2.0*Sigma*gamDu3-3.0 *sigDu3); double te1Dv3 = alpha/32.0*(2.0*Delta*delDv3-2.0*Del_3*delDv3); double te2Dv3 = beta/6.0*(2.0*Sigma*gamDv3-3.0 *sigDv3); double te1Dw3 = alpha/32.0*(2.0*Delta*delDw3-2.0*Del_3*delDw3); double te2Dw3 = beta/6.0*(2.0*Sigma*gamDw3-3.0 *sigDw3); double te1Dx3 = alpha/32.0*(2.0*Delta*delDx3-2.0*Del_3*delDx3); double te2Dx3 = beta/6.0*(2.0*Sigma*gamDx3-3.0 *sigDx3); double epDu0 = volA * ( te1Du0 + te2Du0); double epDv0 = volA * ( te1Dv0 + te2Dv0); double epDw0 = volA * ( te1Dw0 + te2Dw0); double epDx0 = volA * ( te1Dx0 + te2Dx0); double epDu1 = volA * ( te1Du1 + te2Du1); double epDv1 = volA * ( te1Dv1 + te2Dv1); double epDw1 = volA * ( te1Dw1 + te2Dw1); double epDx1 = volA * ( te1Dx1 + te2Dx1); double epDu2 = volA * ( te1Du2 + te2Du2); double epDv2 = volA * ( te1Dv2 + te2Dv2); double epDw2 = volA * ( te1Dw2 + te2Dw2); double epDx2 = volA * ( te1Dx2 + te2Dx2); double epDu3 = volA * ( te1Du3 + te2Du3); double epDv3 = volA * ( te1Dv3 + te2Dv3); double epDw3 = volA * ( te1Dw3 + te2Dw3); double epDx3 = volA * ( te1Dx3 + te2Dx3); double eDu0 = eDep * epDu0; double eDv0 = eDep * epDv0; double eDw0 = eDep * epDw0; double eDx0 = eDep * epDx0; double eDu1 = eDep * epDu1; double eDv1 = eDep * epDv1; double eDw1 = eDep * epDw1; double eDx1 = eDep * epDx1; double eDu2 = eDep * epDu2; double eDv2 = eDep * epDv2; double eDw2 = eDep * epDw2; double eDx2 = eDep * epDx2; double eDu3 = eDep * epDu3; double eDv3 = eDep * epDv3; double eDw3 = eDep * epDw3; double eDx3 = eDep * epDx3; { if (vVar.e[iu]) { eDc[iu,0] = eDc[iu,0] + eDu0; eDc[iu,1] = eDc[iu,1] + eDu1; eDc[iu,2] = eDc[iu,2] + eDu2; eDc[iu,3] = eDc[iu,3] + eDu3; } if (vVar.e[iv]) { eDc[iv,0] = eDc[iv,0] + eDv0; eDc[iv,1] = eDc[iv,1] + eDv1; eDc[iv,2] = eDc[iv,2] + eDv2; eDc[iv,3] = eDc[iv,3] + eDv3; } if (vVar.e[iw]) { eDc[iw,0] = eDc[iw,0] + eDw0; eDc[iw,1] = eDc[iw,1] + eDw1; eDc[iw,2] = eDc[iw,2] + eDw2; eDc[iw,3] = eDc[iw,3] + eDw3; } if (vVar.e[ix]) { eDc[ix,0] = eDc[ix,0] + eDx0; eDc[ix,1] = eDc[ix,1] + eDx1; eDc[ix,2] = eDc[ix,2] + eDx2; eDc[ix,3] = eDc[ix,3] + eDx3; } } } Distribute_eDep; { /* Clear potential energy accumulators: */ for (j = 0; j < NP; j++){ ep[j] = 0.0; } /* Accumulate potential energy of each tetrahedron */ for (j = 0; j < NP; j++) { if (polyRelevant[j]) { Accum_ep(j, ep[j]); } } /* Compute energy "e" from cells determinants, and the gradient "eDdet": */ e = 0.0; for (p = 0; p < NP; p++) { if (polyRelevant[p]) { Accum_e_from_ep(ep[p], e, eDep[p]); } else { eDep[p] = 0.0 } } /* Now distribute "eDdet" over "eDc": */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, ..}; } if (grad) { for (j = 0; j < NP; j++) { if (polyRelevant[j]) { Distribute_eDep(j,eDep[j]) } } } } } } /* END Eval */ char * SELF_Name(SELF_T *erg)== { return "Elasticity(alpha="&Fmt.LongReal(erg->alpha,Fmt.Style.Fix,prec=2) \ " beta="&Fmt.LongReal(erg->beta,Fmt.Style.Fix,prec=2)&")"; } /* END Name */ { } ElasticityEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/EquaAngleEnergy.c /* See {EquaAngleEnergy.h} */ // #INCLUDE // #INCLUDE #include #include // #INCLUDE // #INCLUDE TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; DRF == REF uint_vec_t; Wall == Triangulation.Wall; @{Edge->?} == Triangulation.edge; WALLS == Wall_vec_t; Cosines == REF double_vec_t; Walls == REF WALLS; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ @{edge->?}Relevant: REF bool_vec_t; /* TRUE if @{edge->?} is relevant */ cosine: REF ARRAY OF Cosines; /* The diedral angles */ DRF drf; /* The Walls Ring Degree for @{edge->?} */ walls: REF Wall_vec_ts; /* The walls-ring for @{edge->?} */ eDcosine: REF ARRAY OF Cosines; /* (Work) Gradient of "e" rel. to the dihedral average angle "a". */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->edgeRelevant = bool_vec_new(top->NE); erg->walls = CollectWallsRing(top); erg->drf = ComputeWallRingDegree(erg->walls,top); erg->K = 1.0; erg->cosine = NEW(REF ARRAY OF Cosines, top->NE); erg->eDcosine = NEW(REF ARRAY OF Cosines, top->NE); for (i = 0; i < top->NE; i++) { erg->cosine[i] = double_vec_new(erg->drf^[i]) } for (i = 0; i < top->NE; i++) { erg->eDcosine[i] = double_vec_new(erg->drf^[i]) } /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->NE; i++){ erg->edgeRelevant[i] = FALSE; } } /* END DefTop */ WALLS *CollectWalls( @{Edge->?} *e; *ElemTableRec_t *top; )== uint NT = 0; uint ct; { int NF = top->wall.ne; ??? t = Wall_vec_new(NF)^; { for (i = 0; i < NF; i++) { ct = 0; ??? f = top->wall[i]; ??? fun = f.node[0]->num; ??? fvn = f.node[1]->num; ??? fwn = f.node[2]->num; ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { if (((fun == eun) || (fun == evn))){ ct++; } if (((fvn == eun) || (fvn == evn))){ ct++; } if (((fwn == eun) || (fwn == evn))){ ct++; } if (ct == 2) { t[NT] = f; NT++; } } } ??? r = Wall_vec_new(NT); { r^ = SUBARRAY(t,0,NT); return r; } } } CollectWalls; DRF ComputeWallRingDegree(*walls: REF Wall_vec_ts, ElemTableRec_t *top) { ??? drf = NEW(DRF, top->NE); { for (l = 0; l < top->NE; l++) { ??? fie = walls[l]; { drf^[l] = ((fie^).ne); } } return drf; } } ComputeWallRingDegree; Wall_vec_ts *CollectWallsRing(ElemTableRec_t *top)== { ??? walls = NEW(REF Wall_vec_ts, top->NE); { for (l = 0; l < top->NE; l++) { ??? e = top->edge[l]; ??? fie = CollectWalls(e, top); { walls[l] = fie; } } return walls; } } CollectWallsRing; void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) n : uint = 0; { /* This energy is computed only for edges that exist, have DegreeRingWalls three or more, and have only existing walls and nodes incident to them. */ int NV = erg->top->node.ne; ??? NE = erg->top->NE; bool_vec_t vVar = erg->vVar^; ??? @{edge->?} = erg->top->edge^; ??? @{edge->?}Relevant = erg->edgeRelevant^; ??? drf = erg->drf^; ??? walls = erg->walls^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant @{edge->?}s: */ for (i = 0; i < NE; i++){ @{edge->?}Relevant[i] = FALSE; } VAR bool_t fexists,pexists,interface,interpoly; { for (i = 0; i < NE; i++) { ??? e = @{edge->?}[i]; ??? u = e.node[0]; ??? v = e.node[1]; ??? vvar = vVar.e[u->num]) || (vVar.e[v->num]; ??? de = drf[e->num]; ??? cf = walls[e->num]; { for (j = 0; j < de; j++) { ??? f1 = cf^[j]; ??? a = f1.pa^; ??? aPpos = Ppos(a); ??? aPneg = Pneg(a); { IF( aPpos!= NULL)) && ((aPneg!=NULL) )){ interpoly = TRUE; } else { interpoly = FALSE; } if (f1->exists ){ interface = TRUE; } else { interface = FALSE; } fexists = f1->exists) && (pexists; } fexists = TRUE) && (interface; pexists = TRUE) && (interpoly; } if ((e->exists) && (fexists) && (pexists) && (vvar) && ( de >= 3)) { ??? u = NARROW(u, Triangulation.Node); ??? v = NARROW(v, Triangulation.Node); { assert(u->exists) && (v->exists); } @{edge->?}Relevant[i] = TRUE; n++; } else { @{edge->?}Relevant[i] = FALSE; } } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NE = erg->top->NE; ??? @{edge->?} = erg->top->edge^; ??? @{edge->?}Relevant = erg->edgeRelevant^; ??? cosine = erg->cosine^; ??? K = erg->K; ??? drf = erg->drf^; ??? walls = erg->walls^; ??? eDcosine = erg->eDcosine^; ??? vVar = erg->vVar; { void Compute_cosine( *f1,f2: Place_t; double *cos; ) /* Compute the diedral angle between the walls f1 and f2. */ { ??? a = f1; ??? b = f2; Node_t ao = OrgV(a)->num; Node_t ad = OrgV(NextE(a))->num; Node_t ae = OrgV(PrevE(a))->num; Node_t bo = OrgV(b)->num; Node_t bd = OrgV(NextE(b))->num; Node_t be = OrgV(PrevE(b))->num; ??? v1a = r4_Sub(c[ad], c[ao]); ??? v2a = r4_Sub(c[ae],c[ao]); ??? v1b = r4_Sub(c[bd],c[bo]); ??? v2b = r4_Sub(c[be],c[bo]); ??? p1 = FindOrthogonal(v1a,v2a); ??? p2 = FindOrthogonal(v1b,v2b); ??? m = r4_Norm(p1); ??? n = r4_Norm(p2); ??? o = r4_dot(p1,p2); ??? d = m * n; { assert(ao == bo) && (ad == bd); cos = o/d; /*fprintf(stderr, Fmt.LongReal(cos) & "\n");*/ } } Compute_cosine; r4_t FindOrthogonal(*v1,v2: r4_t) /* compute a orthogonal vector to v1, by the Gram-Schmidt decomposition. */ { ??? u1 = v1; ??? v2_u1 = r4_Project(v2, u1); ??? u2 = r4_Sub(v2, 2_u1); { return u2; } } FindOrthogonal; void Accum_e_from_cosine( double cos; uint d; double *eDcos; ) /* Adds to "e" the energy term corresponding to dihedral average angle "a". */ { ??? thetan = 2.0 * FLOAT(Math.Pi, double); double theta = thetan/((double)d); double cosideal = Math.cos(theta); double sinideal = Math.sin(theta); double cos2 = cos * cos; double sqr = sqrt(1.0-cos2); double first = cosideal * cos; double secon = sinideal * sqr; double nund = sinideal * cos; double firstd = nund/sqr; { e = e + K * ( 1.0 - 2.0 * (first+secon)); if (grad) { eDcos= 2.0 * (firstd - cosideal); } else { eDcos = 0.0; } } } Accum_e_from_cosine; void Distribute_eDcosine( *f1,f2: Place_t; double *eDcos; ) { ??? a = f1; ??? b = f2; Node_t ao = OrgV(a)->num; Node_t ad = OrgV(NextE(a))->num; Node_t ae = OrgV(PrevE(a))->num; Node_t be = OrgV(PrevE(b))->num; ??? v1a = r4_Sub(c[ad], c[ao]); ??? v2a = r4_Sub(c[ae],c[ao]); ??? v2b = r4_Sub(c[be],c[ao]); ??? p1 = FindOrthogonal(v1a,v2a); ??? p2 = FindOrthogonal(v1a,v2b); ??? m = r4_Norm(p1); ??? n = r4_Norm(p2); ??? o = r4_dot(p1,p2); ??? d = m * n; ??? q = o/d; ??? f1 = r4_Cos(v2a,v1a); ??? f2 = r4_Cos(v2b,v1a); ??? eDo = eDcos/d; ??? eDd = - eDcos * q / d; ??? eDm = eDd * n; ??? eDn = eDd * m; { r4_t eDp1 = r4_Mix(eDo, p2, eDm/m, p1); r4_t eDp2 = r4_Mix(eDo, p1, eDn/n, p2); r4_t eDv1a = r4_Mix(-f1,eDp1,-f2,eDp2); r4_t eDv2a = r4_Neg(eDp1); r4_t eDv2b = r4_Neg(eDp2); if (grad) { if (vVar.e[ao]) { eDc[ao]= r4_Sub(eDc[ao],r4_Add(r4_Add(eDv1a,eDv2a),eDv2b)); } if (vVar.e[ad]) { eDc[ad] = r4_Add(eDc[ad],eDv1a); } if (vVar.e[ae]) { eDc[ae] = r4_Add(eDc[ae],eDv2a); } if (vVar.e[be]) { eDc[be] = r4_Add(eDc[be],eDv2b); } } } } Distribute_eDcosine; { /* Clear dihedral angle and their derivative accumulators: */ for (j = 0; j < NE; j++) { for (i = 0; i <= (drf[j]-1); i++) { cosine[j,i] = 0.0; eDcosine[j,i] = 0.0; } } for (i = 0; i < NV; i++) { eDc[i] = (r4_t){0.0,0.0,0.0,0.0}; } /* Enumerate @{edge->?}s and accumulate diedral angles: */ for (j = 0; j < NE; j++) { if (@{edge->?}Relevant[j]) { ??? e = @{edge->?}[j]; ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; ??? fie = walls[e->num]; { VAR ao,Place_t @p; uint i = 0; { ao = fie[0].pa^; a = ao; do { Node_t a00 = OrgV(a)->num; ??? a11 = OrgV(Clock(a))->num; Place_t b = NextF(a); { assert((a00 == eun) || (a00 == evn) AND (a11 == eun) || (a11 == evn) ); Compute_cosine(a,b,cosine[j,i]); i++; a = b; } } while (!( ( a == ao) )); } } } } /* Compute energy "e" from dihedral angles, and the gradient "eDda": */ e = 0.0; for (j = 0; j < NE; j++) { ??? ee = @{edge->?}[j]; ??? fie = walls[ee->num]; ??? de = drf[ee->num]; { if (@{edge->?}Relevant[j]) { for (i = 0; i < de; i++) { ??? f1 = fie[i]; ??? af1 = f1.pa^; Place_t af2 = NextF(af1); { Accum_e_from_cosine(cosine[j,i],de,eDcosine[j,i]); if (grad) { Distribute_eDcosine(af1,af2,eDcosine[j,i]); } } } } } } } } } /* END Eval */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Angle()"; } /* END Name */ { } EquaAngleEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ExcenEnergy.c /* See {ExcenEnergy.h} */ // #INCLUDE // #INCLUDE #include // #INCLUDE // #INCLUDE REVEAL T == Public BRANDED OBJECT ElemTableRec_t *top; double K; /* Energy normalization factor */ vVar: REF ARRAY OF bool_t; /* Tells which nodes are variable */ termVar: REF ARRAY OF bool_t; /* Tells which terms are variable */ deg: REF uint_vec_t; /* Effective degree of each node */ org, dst: REF uint_vec_t; /* Directed @{edge->?}s of computed terms */ uint nP; /* Number of @{edge->?}s in "org", "dst" */ sum: REF r4_vec_t; /* (Work) Sum of effective neighbors */ eDsum: REF r4_vec_t; /* (Work) Gradient of "e" rel "sum" */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } CONST Zero == (r4_t){0.0, 0.0, 0.0, 0.0}; SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->top = top; erg->K = ((double)top->node.ne); erg->vVar = NEW(REF ARRAY OF bool_t, top->node.ne); erg->termVar = NEW(REF ARRAY OF bool_t, top->node.ne); erg->deg = NEW(REF uint_vec_t , top->node.ne); erg->org = NEW(REF uint_vec_t , 2*top->NE); erg->dst = NEW(REF uint_vec_t , 2*top->NE); erg->sum = r4_vec_new(top->node.ne); erg->eDsum = r4_vec_new(top->node.ne); /* In case the client forgets to call "defVar": */ erg->NP = 0; for (i = 0; i < top->node.ne; i++) { erg->vVar.e[i] = FALSE; erg->termVar[i] = FALSE } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, *variable: ARRAY OF bool_t) { /* Decide which terms are variable, and compute effective degrees "erg->deg[v]". There is a term for each existing node. The term of "v" is variable if "v" is variable or has some effective neighbor that is variable. */ ??? NP = erg->NP; int NV = erg->top->node.ne; ??? NE = erg->top->NE; ??? @{edge->?} = erg->top->edge^; bool_vec_t vVar = erg->vVar^; ??? termVar = erg->termVar^; ??? org = erg->org^; ??? dst = erg->dst^; ??? deg = erg->deg^; { assert((variable.ne) == NV); vVar = variable; /* If a node is vVar, its term is vVar: */ for (v = 0; v < NV; v++) { termVar[v] = vVar.e[v]; deg[v] = 0 } /* Enumerate effective @{edge->?}s and accumulate efective degrees. */ /* Also set "termVar[v]" if "v" has a vVar effective neighbor. */ for (i = 0; i < NE; i++) { ??? e = @{edge->?}[i]; ??? u = NARROW(OrgV(e.pa), Triangulation.Node); ??? v = NARROW(OrgV(Clock(e.pa)), Triangulation.Node); ??? un = u->num; ??? vn = v->num; { INC(deg[un]); INC(deg[vn]); termVar[un] = termVar[un]) || (vVar.e[vn]; termVar[vn] = termVar[vn]) || (vVar.e[un]; } } /* A node with no effective neighbors (deg[v]==0) has energy zero by definition (termVar[v]==FALSE): */ for (v = 0; v < NV; v++) { if (deg[v] == 0){ termVar[v] = FALSE;} } /* Now collect all efective directed @{edge->?}s "(org[k], dst[k])" */ /* whose origin "org[k]" is variable: */ NP = 0; for (i = 0; i < NE; i++) { ??? e = @{edge->?}[i]; Node_t u = OrgV(e.pa); ??? un = u->num; Node_t v = OrgV(Clock(e.pa)); ??? vn == v->num; { if (termVar[un]){ org[NP] = un; dst[NP] = vn; NP++; } if (termVar[vn]){ org[NP] = vn; dst[NP] = un; NP++; } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { ??? NP = erg->NP; int NV = erg->top->node.ne; bool_vec_t vVar = erg->vVar^; ??? termVar = erg->termVar^; ??? deg = erg->deg^; ??? org = erg->org^; ??? dst = erg->dst^; ??? sum = erg->sum^; ??? eDsum = erg->eDsum^; ??? K = erg->K; { void Compute_sum () /* Computes "sum[v]" for all relevant terms "v" */ { for (v = 0; v < NV; v++) { if (termVar[v]){ sum[v] = Zero;} } for (i = 0; i < NP; i++) { ??? v = org[i], u == dst[i]; { assert(termVar[v]); sum[v] = r4_Add(sum[v], c[u]) } } } Compute_sum; void EvalTerm( *cv, sumv: r4_t; uint degv; double *ev; VAR evDcv, evDsumv: r4_t; ) /* Computes the energy term "ev" for a node at "cv", given the sum of its "relevant neighbors" "sumv". Returns also the gradients "evDcv" and "evDsumv" of "ev" relative to "cv" and "sumv". */ { ??? f = 1.0/((double)degv); ??? barv = r4_Scale(f, sumv); ??? rv = r4_Sub(cv, barv); { ev = K * r4_NormSqr(rv); if (grad) { evDcv = r4_Scale(2.0 * K, rv); evDsumv = r4_Scale(-2.0 * f * K, rv) } else { evDcv = Zero; evDsumv = Zero } } } EvalTerm; void Distribute_eDsum () /* Adds to the derivatives "eDc[u]" the indirect terms represented by "eDsum[v]", for all computed terms "v" that have "u" as a relevant neighbor. */ { for (i = 0; i < NP; i++) { ??? v = org[i], u == dst[i]; { if (vVar.e[u]) { eDc[u] = r4_Add(eDc[u], eDsum[v]) } } } } Distribute_eDsum; double *ev; { Compute_sum(); e = 0.0; for (v = 0; v < NV; v++) { if (termVar[v]) { EvalTerm(c[v], sum[v], deg[v], ev, eDc[v], eDsum[v]); e = e + ev } else { eDc[v] = Zero; } } if (grad){ Distribute_eDsum();} } } } /* END Eval */ PROCEDURE Name(<*UNUSED); erg: T): char *== { return "Excen()"; } /* END Name */ { } ExcenEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Heuristic.c /* See {Heuristic.h} */ // #INCLUDE // #INCLUDE // #INCLUDE void DisplaceNode(Place_t @p, Coords_t *c, bool_vec_t *variable, ElemTableRec_t *top, /* UNUSED */ coins : rand_t; ) { Node_t u = OrgV(a); ??? un = u->num; ??? star = Triangulation.Neighbors(a,top); ??? bar = Triangulation.NeighborBarycenter(star,c); ??? bar0 = bar[0]; ??? bar1 = bar[1]; ??? bar2 = bar[2]; ??? bar3 = bar[3]; { if ((variable[un]) && (u->exists )){ ??? cun = c[un]; { cun[0] = bar0; cun[1] = bar1; cun[2] = bar2; cun[3] = bar3; } } } } /* END DisplaceNode */ { } Heuristic. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Heuristics.c /* See {Heuristics.h} */ // #INCLUDE // #INCLUDE // #INCLUDE #include #include // #INCLUDE #include // #INCLUDE #include #include CONST debug == FALSE; TYPE Node == Triangulation.Node; Wall == Triangulation.Wall; @{Edge->?} == Triangulation.edge; @{EDGE->?}S == Edge_vec_t; WALLS == Wall_vec_t; Walls == REF WALLS; DRF == REF uint_vec_t; /* r4_t Dir(v: r4_t) /* Same as r4_Dir(v), but returns random unit vector if "v" is zero. */ { ??? s = r4_Norm(v); { if (s == 0.0) { return (r4_t){1.0, 0.0, 0.0, 0.0}; } else { return r4_Scale(1.0/s, v); } } } /* END Dir */ Node ChooseReferenceNode( Place_t @p; bool_vec_t *variable; rand_t *coins ) /* If any of the edges out of "Org(a)" has a fixed tip, picks one such @{edge->?}, with probability proportional to the number of "ONext"s until the next fixed @{edge->?}. Otherwise picks a random arc out of "Org(a)". */ v : REF Node_vec_t; { ??? star = Triangulation.NeighborNode(a,top); ??? nv = Triangulation->numberNeighborNode(star); ??? k = coins.integer(0, nv-1); { Node_vec_t v = Node_vec_new(nv); for (j = 0; j < nv; j++) { v[j] = star[j]; } for (i = 0; i < k; i++) { if (! variable[v[i]->num]){ return a; } a = OPrev(a) } return a; } } /* END ChooseReferenceArc */ */ @{EDGE->?}S *Collect@{Edge->?}s(*u: Node; ElemTableRec_t *top)== uint NT = 0; { ??? NE = top->NE; ??? t = Edge_vec_new(NE)^; { for (i = 0; i < NE; i++) { ??? e = top->edge[i]; ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { if (((eun == u->num) || (evn == u->num))) { t[NT] = e; NT++; } } } ??? r = Edge_vec_new(NT); { r^ = SUBARRAY(t,0,NT); return r; } } } /* END Collect@{Edge->?}s */ WALLS *CollectWalls(*e: @{Edge->?}; ElemTableRec_t *top)== uint NT = 0; uint ct; { int NF = top->wall.ne; ??? t = Wall_vec_new(NF)^; { for (i = 0; i < NF; i++) { ct = 0; ??? f = top->wall[i]; ??? fun = f.node[0]->num; ??? fvn = f.node[1]->num; ??? fwn = f.node[2]->num; ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { if (((fun == eun) || (fun == evn))){ ct++; } if (((fvn == eun) || (fvn == evn))){ ct++; } if (((fwn == eun) || (fwn == evn))){ ct++; } if (ct == 2) { t[NT] = f; NT++; } } } ??? r = Wall_vec_new(NT); { r^ = SUBARRAY(t,0,NT); return r; } } } CollectWalls; /* UNUSED */ DRF ComputeWallRingDegree(*walls: REF Wall_vec_ts, ElemTableRec_t *top) { ??? drf = NEW(DRF, top->NE); { for (l = 0; l < top->NE; l++) { ??? fie = walls[l]; { drf^[l] = ((fie^).ne); } } return drf; } } /* END ComputeWallRingDegree */ /* UNUSED */ Wall_vec_ts *CollectWallsRing(ElemTableRec_t *top)== { ??? walls = NEW(REF Wall_vec_ts, top->NE); { for (l = 0; l < top->NE; l++) { ??? e = top->edge[l]; ??? fie = CollectWalls(e,top); { walls[l] = fie; } } return walls; } } /* END CollectWallsRing */ /* UNUSED */ double ComputeWallRingDegreeTotal(*drf: DRF) n : uint = 0; { for(l = 0; l < drf.ne; l++){ ??? d = drf^[l]; { n = n + d; } } return ((double)n); } /* END ComputeWallRingDegreeTotal */ PROCEDURE EquaAngle(Place_t @p, Coords_t *c, bool_vec_t *variable, ElemDataRec_t *top; ) { Node_t u = OrgV(a); ??? @{edge->?}s = Collect@{Edge->?}s(u,top); { for (j = 0 TO LAST(@{edge->?}s^)) { ??? e = @{edge->?}s^[j]; ??? fe = CollectWalls(e,top); { EqualizeDiedralAngle(e,fe,c,u); } } } } /* END EquaAngle */ void EqualizeDiedralAngle(e : @{Edge->?}; *f : REF WALLS; Coords_t *c; *u : Node) { ??? eu = e.node[0]; ??? ev = e.node[1]; ??? m == ((f^).ne); ??? angle == 2.0 * ((double)Math.Pi)/((double)m); { for (i = 0; i < m; i++) { ???; } } } /* END EqualizeDiedralAngle */ /* UNUSED */ PROCEDURE CollectWingPoint(*ff: REF WALLS; @{Edge->?} *e; ) : REF uint_vec_t == /* Retorna para cada aresta o conjunto de nodes dobradicas */ CONST INIT_STACK_SIZE == 10000; stack = NEW(REF uint_vec_t ,INIT_STACK_SIZE); uint nstack = 0; bool_t Present(n : uint) uint nstack1 = nstack; VAR { while (nstack1 > 0) { nstack1 = nstack1 - 1; if (stack.e[nstack1] == n){ return TRUE; } } return FALSE; } Present; { ??? fi = ff^[0]; ??? wingi = WingPoint(e, fi); { stack.e[nstack] = wingi; nstack++; } for(i = 1; i < ff.ne; i++) { ??? f = ff^[i]; ??? wing = WingPoint(e, f); { if ((! Present(wing))){ stack.e[nstack] = wing; nstack++; } } } ??? r = NEW(REF uint_vec_t, nstack); { r^ = SUBARRAY(stack^, 0, nstack); return r; } } /* END CollectWingPoint */ uint WingPoint(*e: @{Edge->?}; *f: Wall) uint *wp; { ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; ??? fn = f.node; { for (i = 0; i < 3; i++) { if (((fn[i]->num!=eun) && (fn[i]->num!=evn) )){ wp = fn[i]->num; } } } return wp; } /* END WingPoint */ /* void FlattenNode( Arc a; Coords_t *c; bool_vec_t *variable; <*UNUSED); rand_t *coins; ) == somaki: double = 0.0; somakiti: double = 0.0; uint n = 0; void CalcTi(*bar: r3_t; e: Arc) /* Computes the pseudo-force "ti" and its weight "ki" and accumulates them in "somatiki", "somaki" */ { /* Check if hinge exists and has a spring: */ ??? b = OPrev(Sym(e)); ??? be = NARROW(b.edge, Triang.edge); ??? bl = LeftF(b); ??? br = LeftF(Sym(b)); { if ((! (bl->exists) && (br->exists) && (be.spring))){ return;} } /* Do the computations: */ ??? f = ONext(e); Node_t p = OrgV(Sym(e))->num; Node_t q = OrgV(Sym(f))->num; Node_t w = OrgV(Sym(ONext(ONext(Sym(f)))))->num; ??? di = r3_sub(c[q], c[p]); ??? ni = LR3Extras.Cross(di, r3_sub(bar, c[q])); ??? mi = LR3Extras.Cross(r3_sub(c[w], c[p]), di); ??? dimod = LR3.Norm(di); ??? nimod = LR3.Norm(ni); ??? mimod = LR3.Norm(mi); ??? sinTheta = LR3x3.Det(LR3x3.T{ni, mi, di}) / (nimod*mimod*dimod); ??? cosTheta = LR3.Cos(ni, mi); ??? theta = Math.atan2(sinTheta, cosTheta); ??? feta = ThetaFunc(theta); ??? ki = dimod; ??? ti = feta * nimod / dimod; { if (debug) { Debug.LongReal("CalcTi: ni == ", ni); Debug.LongReal(" mi == ", mi); Debug.LongReal(" di == ", di); Debug.LongReal(" sin, cos == ", LRN.T{sinTheta, cosTheta}); Debug.LongReal(" theta, feta == ", LRN.T{theta, feta}); Debug.LongReal(" ki, ti == ", LRN.T{ki, ti}); } somaki = somaki + ki; somakiti = somakiti + ki * ti; N = N+1; } } CalcTi; double ThetaFunc(Theta: double) CONST PPi == ((double)Math.Pi); PiCube == PPi * PPi * PPi; B == 0.5; A == (1.0 - B*PPi) / PiCube; { ??? ThetaCube = Theta * Theta * Theta; { return A * ThetaCube + B * Theta; } } ThetaFunc; Arc *an; { Node_t vx = OrgV(a); ??? v = vx->num; ??? bar = Triang.NeighborBarycenter(a,c); ??? n = Triang.NodeNormal(a, c); { if ((! variable[v]) && (vx->exists)){ return; } if (debug){ Debug.LongReal(" bar == ", bar); } an = a; do { CalcTi(bar, an); an = ONext(an) } while (an != a); ??? t = somakiti / somaki; Node_t ao = OrgV(a)->num; ??? u = r3_add(bar, r3_scale(t, n)); { if (debug) { Debug.LongReal(" t == ", LRN.T{t}); Debug.LongReal(" n == ", n); Debug.LongReal(" u == ", u); } c[ao] = u; } } } /* END FlattenNode */ */ { } Heuristics. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/HingeEnergy.c /* See {HingeEnergy.h} */ // #INCLUDE #include #include // #INCLUDE // #INCLUDE TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; DRF == REF uint_vec_t; EndPoints == ARRAY [0..1] OF uint; Wall == Triangulation.Wall; @{Edge->?} == Triangulation.edge; WALLS == Wall_vec_t; Walls == REF WALLS; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ @{edge->?}Relevant: REF bool_vec_t; /* TRUE if @{edge->?} is relevant */ da: REF double_vec_t; /* The average diedral angles */ DRF drf; /* The Walls Ring Degreee for @{edge->?}*/ walls: REF Wall_vec_ts; /* The walls-ring for @{edge->?} */ zmDbe : REF r4_vec_t; OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { ??? NP = FLOAT(top->cell.ne, double); { erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->edgeRelevant = bool_vec_new(top->NE); erg->walls = CollectWallsRing(top); erg->drf = ComputeWallRingDegree(erg->walls,top); erg->K = 1.0/(2.0*Math.pow(NP,5.0/3.0)); /* Allocate average dihedral angle tables: */ erg->da = double_vec_new(top->NE); erg->zmDbe = r4_vec_new(top->NE); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->NE; i++){ erg->edgeRelevant[i] = FALSE; } } } /* END DefTop */ Wall_vec_t *CollectWalls(*e: @{Edge->?}; ElemTableRec_t *top)== /* Return the set of walls incidents to @{edge->?} "e" */ uint NT = 0; uint ct; { int NF = top->wall.ne; ??? t = Wall_vec_new(NF)^; { for (i = 0; i < NF; i++) { ct = 0; ??? f = top->wall[i]; ??? fn = f.node; ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { for (j = 0; j < 3; j++) { if (((fn[j]->num == eun) || (fn[j]->num == evn))){ ct++; } } if (ct == 2) { t[NT] = f; NT++; } } } ??? r = Wall_vec_new(NT); { r^ = SUBARRAY(t,0,NT); return r; } } } CollectWalls; DRF ComputeWallRingDegree(*walls: REF Wall_vec_ts, ElemTableRec_t *top) { ??? drf = NEW(DRF, top->NE); { for (l = 0; l < top->NE; l++) { ??? fie = walls[l]; { drf^[l] = ((fie^).ne); } } return drf; } } ComputeWallRingDegree; Wall_vec_ts *CollectWallsRing(ElemTableRec_t *top)== { ??? walls = NEW(REF Wall_vec_ts, top->NE); { for (l = 0; l < top->NE; l++) { ??? e = top->edge[l]; ??? fie = CollectWalls(e, top); { walls[l] = fie; } } return walls; } } CollectWallsRing; /* UNUSED */ double ComputeWallRingDegreeTotal(*drf: DRF) uint n = 0; VAR { for(l = 0; l < drf.ne; l++) { ??? d = drf^[l]; { n = n + d; } } return ((double)n); } ComputeWallRingDegreeTotal; void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* This energy is computed only for edges that have the "hinge" bit set, have DegreeRingWalls three or more, and have only existing walls and variable nodes incident to them. */ int NV = erg->top->node.ne; ??? NE = erg->top->NE; bool_vec_t vVar = erg->vVar^; ??? @{edge->?} = erg->top->edge^; ??? @{edge->?}Relevant = erg->edgeRelevant^; ??? drf = erg->drf^; ??? walls = erg->walls^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant @{edge->?}s: */ for (i = 0; i < NE; i++){ @{edge->?}Relevant[i] = FALSE; } VAR bool_t fexists = TRUE; { for (i = 0; i < NE; i++) { ??? e = @{edge->?}[i]; ??? u = e.node[0]; ??? v = e.node[1]; ??? vvar = vVar.e[u->num]) || (vVar.e[v->num]; ??? de = drf[e->num]; ??? cf = walls[e->num]; { for (j = 0; j < de; j++) { ??? f1 = cf^[j]; ??? f2 = cf^[(j+1) % de]; { fexists = (f1->exists) && (f2->exists)) && (fexists; } } if ((e.hinge) && (fexists) && (vvar) && ( de >= 3)) { ??? u = NARROW(u, Triangulation.Node); ??? v = NARROW(v, Triangulation.Node); { assert(e->exists); assert(u->exists) && (v->exists); } @{edge->?}Relevant[i] = TRUE; } else { @{edge->?}Relevant[i] = FALSE; } } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NE = erg->top->NE; ??? @{edge->?} = erg->top->edge^; ??? @{edge->?}Relevant = erg->edgeRelevant^; ??? da = erg->da^; ??? K = erg->K; ??? drf = erg->drf^; ??? walls = erg->walls^; bool_vec_t vVar = erg->vVar^; ??? zmDbe = erg->zmDbe^; { PROCEDURE Extremus@{Edge->?}(*e: @{Edge->?}) : EndPoints == EndPoints *stack; { ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { stack.e[0] = eun; stack.e[1] = evn; return stack; } } Extremus@{Edge->?}; void ComputeAverageDiedralAngle(*e: @{Edge->?}; double zm; VAR VAR zmDbe: r4_t) double *z; zDbe : r4_t; { ??? fie = walls[e->num]; ??? de = drf[e->num]; ??? del = ((double)de); ??? bi = Extremus@{Edge->?}(e); { zm = 0.0; zmDbe = (r4_t){0.0, ..}; for (i = 0; i < de; i++) { ??? f1 = fie[i]; ??? af1 = f1.pa^; ??? f2 = fie[(i+1) % de]; ??? af2 = f2.pa^; ??? bf1 = WallBarycenter(af1,c); ??? bf2 = WallBarycenter(af2,c); { Compute_z(bf1,bf2,bi,z, zDbe); zm = zm + z; zmDbe = r4_Add(zmDbe, zDbe); } } zm = zm/del; zmDbe = r4_Scale(1.0/del, zmDbe); } } ComputeAverageDiedralAngle; void Compute_z(*bf1,bf2: r4_t; *e: EndPoints; double *z; VAR zDbe: r4_t) /* Compute the diedral angle between the walls planes f1 and f2. */ { ??? u = e[0]; ??? v = e[1]; ??? be = r4_Scale(1.0/2.0, r4_Add(c[u],c[v])); ??? a = r4_Sub(be,bf1); ??? b = r4_Sub(be,bf2); ??? m = r4_Norm(a); ??? n = r4_Norm(b); ??? d = m * n; ??? o = r4_dot(a,b); ??? q = o/d; { z = sqrt( 2.0 * (1.0-q)); /* Aproximation */ if (grad) { ??? zDq = - 2.0; ??? zDo = zDq /d; ??? zDd = - zDq * q / d; ??? zDm = zDd * n; ??? zDn = zDd * m; ??? zDa = r4_Mix(zDo, b, zDm/m, a); ??? zDb = r4_Mix(zDo, a, zDn/n, b); { zDbe = r4_Neg(r4_Add(zDa, zDb)); } } } } Compute_z; void Accum_e_from_ee(zm: double; d: uint; double *e; VAR eDzm: double) /* Adds to "e" the energy term corresponding to hinge @{edge->?} with endpoints "e" and average dihedral angle "zm". */ { ??? idealtetha = 360.0/((double)d); ??? tetha = fabs(zm-idealtetha); { e = e + K * tetha; if (grad) { eDzm = K; } else { eDzm = 0.0; } } } Accum_e_from_ee; void Distribute_eDzm(u,v: uint; double *eDzm; *zmDbe: r4_t) /* Distribute eDzm on endpoints "c[u]" and "c[v]" */ { ??? eDv = eDc[v]; ??? eDu = eDc[u]; ??? eDbe = r4_Scale(eDzm, zmDbe); { ??? eDcu = r4_Scale(1.0/2.0, eDbe); ??? eDcv = r4_Scale(1.0/2.0, eDbe); { if (vVar.e[v]) { eDv = r4_Add(eDv, eDcv); } if (vVar.e[u]) { eDu = r4_Add(eDu, eDcu); } } } } Distribute_eDzm; VAR double eDzm; { /* Clear average dihedral angle accumulators: */ for (j = 0; j < NE; j++){ da[j] = 0.0; zmDbe[j] = (r4_t){0.0,.. }; } /* Enumerate @{edge->?}s and accumulate diedral angles: */ for (j = 0; j < NE; j++) { if (@{edge->?}Relevant[j]) { ??? e = @{edge->?}[j]; { ComputeAverageDiedralAngle(e, da[j], zmDbe[j]); } } } /* Compute energy "e" from dihedral angles, and the gradient "eDvp": */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0,..}; } e = 0.0; for (j = 0; j < NE; j++) { ??? ee = @{edge->?}[j]; ??? de = drf[ee->num]; ??? un = ee.node[0]->num; ??? vn = ee.node[1]->num; { if (@{edge->?}Relevant[j]) { Accum_e_from_ee(da[j],de,e,eDzm); if (grad) { Distribute_eDzm(un, vn, eDzm, zmDbe[j]); } } } } } } } /* END Eval */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Hinge()"; } /* END Name */ { } HingeEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/MixedEnergy.c /* See {MixedEnergy.h} */ // #INCLUDE #include // #INCLUDE #include // #INCLUDE REVEAL T == Public BRANDED OBJECT ekDc: REF r4_vec_t; /* (Work) Gradient of some ingredient */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } T Init(erg: T; *term: ARRAY OF Energy.T; *weight: ARRAY OF REAL) { ??? NT = (term.ne); { assert((weight.ne) == NT); erg->term = NEW(REF ARRAY OF Energy.T, NT); erg->weight = NEW(REF ARRAY OF REAL, NT); erg->termValue = double_vec_new(NT); erg->term^ = term; erg->weight^ = weight; return erg; } } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) /* defTop(), for each energy ingredient */ { ??? term = erg->term^; ??? NT = (term.ne); { erg->ekDc = r4_vec_new(top->node.ne); for (k = 0; k < NT; k++){ term[k].defTop(top);} } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, *variable: ARRAY OF bool_t) /* defVar(), for each energy ingredient */ { ??? term = erg->term^; ??? NT = (term.ne); { for (k = 0; k < NT; k++){ term[k].defVar(variable);} } } /* END DefVar */ void Eval(erg: T; *c: Coords_t; double e; VAR bool_t grad; VAR eDc: Gradient;) /* eval(), for each energy ingredient */ { ??? term = erg->term^; ??? weight = erg->weight^; ??? termValue = erg->termValue^; ??? ekDc = erg->ekDc^; ??? NT = (term.ne); ??? NV = (c.ne); { assert((eDc.ne) == NV); e = 0.0; for (v = 0; v < NV; v++){ eDc[v] = (r4_t){0.0, ..}; } for (k = 0; k < NT; k++) { term[k].eval(c, termValue[k], grad, ekDc); e = e + ((double)weight[k]) * termValue[k]; if (grad) { for (v = 0; v < NV; v++) { eDc[v] = r4_Mix(1.0,eDc[v], ((double)weight[k]), ekDc[v]) } } } } } /* END Eval */ char * SELF_Name(SELF_T *erg)== wr = NEW(TextWr.T).init(); /* escritor de texto */ { ??? term = erg->term^; ??? weight = erg->weight^; ??? NT = (term.ne); { fprintf(wr, "Mixed("); for (i = 0; i < NT; i++) { if (i > 0){ fprintf(wr, ",\n"); } if (i == 0) { fprintf(wr, "["); } else { fprintf(wr, " ["); } fprintf(wr, Fmt.Int(i)); fprintf(wr, "] == "); fprintf(wr, Fmt.Real(weight[i], Fmt.Style.Fix, 2)); fprintf(wr, "·"); fprintf(wr, term[i].name()) } fprintf(wr, ")") } return TextWr.ToText(wr); } /* END Name */ { } MixedEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ModKamSpring.c /* See {ModKamSpring.h} */ // #INCLUDE #define ModKamSpring_C_author \ "Modified by L.A.P.Lozada on 2000-11-18." // #INCLUDE #include // #INCLUDE #include // #INCLUDE CONST inf == (uint.ne-1); TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; AdjacencyMatrix == ARRAY OF uint_vec_t; REVEAL T == Public BRANDED OBJECT ElemTableRec_t *top; /* The map elements. */ termVar: REF bool_vec_t; /* TRUE if node is variable & existing */ m : REF AdjacencyMatrix; /* Matrix of initial distances */ eDdif: REF double_vec_t_vec_t; /* (Work) Gradient of "e" rel. to "dif" */ double L; /* length of spring */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) double *dmax; { ??? NV = top->node.ne; { erg->m = MakeAdjacencyMatrix(top); /*PrintHalfMatrix(erg->m, NV);*/ ShortestPath(erg->m, NV); /*PrintHalfMatrix(erg->m, NV);*/ dmax = FLOAT(FindMaxDistance(erg->m, NV), double); erg->L = FLOAT(erg->length,double)/dmax; erg->top = top; erg->termVar = bool_vec_new(NV); erg->eDdif = double_vec_t_vec_new(NV, NV); /*PrintHalfMatrix(erg->k, NV);*/ /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->termVar^[i] = FALSE; } } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which nodes are relevant to kamada energy. A node is relevant iff it is variable. */ int NV = erg->top->node.ne; ??? termVar = erg->termVar^; { /* Find the relevant nodes: */ assert((variable.ne) == NV); for (v = 0; v < NV; v++) { termVar[v] = variable[v]; } } } /* END DefVar */ AdjacencyMatrix *MakeAdjacencyMatrix(ElemTableRec_t *top, )== REF AdjacencyMatrix m ; { m = NEW(REF ARRAY OF uint_vec_t , top->node.ne, top->node.ne); for (i = 0; i < top->node.ne; i++) { for (j = 0; j < top->node.ne; j++) { m[i,j] = inf; } m[i,i] = 0; } for (i = 0; i < top->NE; i++) { ??? a = top->edge[i].pa; Node_t i = OrgV(a)->num; Node_t j = OrgV(Clock(a))->num; { m[i,j] = 1; m[j,i] = 1; } } return m; } /* END MakeAdjacencyMatrix */ uint FindMaxDistance( *m: REF AdjacencyMatrix; INTEGER n; ) max = 0; { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] > max) { max = m[i,j]; } } } return max; } /* END FindMaxDistance */ double CalculateStrength(dist : uint) { if (dist == 0){ return 0.0; } else { ??? d = ((double)dist); { return 1.0/(d*d); } } } /* END CalculateStrength */ double CalculateLength(dist : uint) { if (dist == 0){ return 0.0; } else { ??? d = ((double)dist); { return d; } } } /* END CalculateLength */ /* UNUSED */ void PrintAdjacencyMatrix(*m : REF AdjacencyMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.Int(m[i,j]) & " "); } } fprintf(stderr, "\n"); } } /* END PrintAdjacencyMatrix */ /* UNUSED */ void PrintHalfMatrix(*m : REF AdjacencyMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.Int(m[i,j]) & " "); } } fprintf(stderr, "\n"); } } /* END PrintHalfMatrix */ void ShortestPath(VAR m : REF AdjacencyMatrix; n : INTEGER) uint *s; { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[j,i] < inf) { for (k = 0; k < n; k++) { if (m[i,k] < inf) { s = m[j,i] + m[i,k]; if (s < m[j,k]){ m[j,k] = s; } } } } } } } ShortestPath; void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? eDdif = erg->eDdif^; ??? termVar = erg->termVar; ??? length = erg->L; ??? strength = ((double)erg->strength); ??? m = erg->m^; { void AccumTerm(*u: uint) /* Adds to "e" the energy term corresponding to a node "u". Returns also the gradient "eDdif". */ CONST Epsilon == 1.0d-10; { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? cv = c[i]; ??? n = r4_Sub(cu,cv); ??? dif = r4_Norm(n); ??? d2 = dif * dif + Epsilon; ??? duv = m[u,i]; ??? luv = length * CalculateLength(duv); ??? kuv = strength * CalculateStrength(duv); ??? l2 = luv * luv + Epsilon; ??? d3 = d2 * dif + Epsilon; { e = e + kuv * ( (d2/l2) + (l2/d2) - 2.0); if (grad) { eDdif[u,i] = 2.0 * kuv * ( (dif/l2) - (l2/d3)); eDdif[i,u] = eDdif[u,i]; } else { eDdif[u,i] = 0.0; eDdif[i,u] = eDdif[u,i]; } } } } } AccumTerm; void Distribute_eDdif(*u: uint) /* Distribute eDdif on endpoints "c[u]" and "c[v]" */ CONST Epsilon == 1.0d-10; { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? ci = c[i]; ??? n = r4_Sub(cu, ci); ??? dif = r4_Norm(n)+Epsilon; ??? eDi = eDc[i]; ??? eDu = eDc[u]; ??? difDcu = r4_Scale(1.0/dif, n); ??? difDci = r4_Scale(-1.0/dif,n); ??? eDcu = r4_Scale(eDdif[u,i], difDcu); ??? eDci = r4_Scale(eDdif[u,i], difDci); { if (termVar[i]) { eDi = r4_Add(eDi, eDci); } if (termVar[u]) { eDu = r4_Add(eDu, eDcu); } } } } } Distribute_eDdif; { for (i = 0; i < NV; i++){ eDc[i]=(r4_t){0.0, 0.0, 0.0, 0.0}; } e = 0.0; for (l = 0; l < NV; l++) { if (termVar[l]) { AccumTerm(l); if (grad) { Distribute_eDdif(l); } } } } } } Eval; char * SELF_Name(SELF_T *erg)== { return "ModKamada(ilenth = " & Fmt.Real(erg->length,Fmt.Style.Fix,prec = 3) \ " istrength = " & Fmt.Real(erg->strength,Fmt.Style.Fix,prec= 3) & ")"; } /* END Name */ { } ModKamSpring. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/MyCurvature2D.c /* See {MyCurvature2D.h} */ // #INCLUDE // #INCLUDE // #INCLUDE #include // #INCLUDE // #INCLUDE CONST zero == (r4_t){0.0,0.0,0.0,0.0}; INIT_STACK_SIZE == 100000; Epsilon == 0.0000000001; VAR str,stc: Stat.T; /* statistical accumulators to the number of "root" elements and the number of "children" elements inside each "root" element. */ TYPE bool_vec_t == ARRAY OF bool_t; StackF == REF Wall_vec_t; Number == RECORD INTEGER nre; /* number of "root" walls. */ uint nce; /* number of "children" walls inside each "root" wall.*/ } REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ Number num; /* Number of "root" and "children" walls*/ ChilWall: REF ARRAY OF StackF; /* The "children" walls */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } Number Statistics(ElemTableRec_t *top) Number *num; { for (i = 0; i < top->wall.ne; i++){ ??? f = top->wall[i]; ??? fr = FLOAT(f->root, REAL); { Stat.Accum(str,fr); if (fr == 0.0){ Stat.Accum(stc,fr); } } } num.nre = FLOOR(str.maximum)+1; num.nce = FLOOR(stc->num); return num; } /* END Statistics */ PROCEDURE CropChilWalls( ElemTableRec_t *top; Number *num; ) : REF ARRAY OF StackF == topi : REF uint_vec_t; /* Crop the "children" walls for each "root" wall. */ { /* initialize the "top" indexes for each of the "num.nre" stacks of walls. */ topi = NEW(REF uint_vec_t , num.nre); for (k = 0; k < num.nre; k++){ topi[k] = 0; } ??? t = NEW(REF ARRAY OF StackF, num.nre); { for (k = 0; k < num.nre; k++) { t[k] = Wall_vec_new(INIT_STACK_SIZE); } for (j = 0; j < top->wall.ne; j++) { ??? f = top->wall[j]; ??? fr = f->root; { if (fr!=-1){ SaveF(t[fr],topi[fr],f); } } } return t; } } /* END CropChilWalls */ void SaveF( StackF *Stack; uint *top; Wall *wall; ) /* Save the wall "wall" on the stack "Stack" */ { Stack.El[top] = wall; top = top +1 } /* END SaveF */ SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0; erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->num = Statistics(top); erg->ChilWall = CropChilWalls(top,erg->num); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { int NV = erg->top->node.ne; ??? vVar = erg->vVar^; { assert((variable.ne) == NV); vVar = variable; } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { ??? NV = erg->top->node.ne; ??? K = erg->K; ??? vVar = erg->vVar^; ??? ChilWall = erg->ChilWall; ??? num = erg->num; { void AddTerm(*iu,iv,iw,ix: uint) /* Adds one term of the curvature energy to "e" (and its derivative to "eDc, if "grad" is TRUE). The terms correspond to the walls "f1 == u v w" and "f2 == u w x". See the follow picture: v /|\ / | \ / | \ / / | \ \ ------ w / | \ x ----- \ \ f1 | f2 / / \ | / \ | / \ | / \|/ u */ double eterm ; eDdu, eDdv, eDdw, eDdx: r4_t; { ??? u = c[iu]; ??? v = c[iv]; ??? w = c[iw]; ??? x = c[ix]; { term(u,v,w,x, eterm, eDdu, eDdv, eDdw, eDdx); e = e + eterm; if (grad) { if (vVar.e[iu]) { eDc[iu] = r4_Add(eDc[iu],eDdu); } if (vVar.e[iv]) { eDc[iv] = r4_Add(eDc[iv],eDdv); } if (vVar.e[iw]) { eDc[iw] = r4_Add(eDc[iw],eDdw); } if (vVar.e[ix]) { eDc[ix] = r4_Add(eDc[ix],eDdx); } } } } AddTerm; void term(u,v,w,x: r4_t; double *eterm; VAR dedu,dedv,dedw,dedx: r4_t; ) VAR dedDv,dedDw,dedDx: r4_t; { r4_t Dv = r4_Sub(v, u); /* V */ r4_t Dw = r4_Sub(w, u); /* V */ r4_t Dx = r4_Sub(x, u); { EangleAux(Dv,Dw, Dx, eterm, dedDv,dedDw,dedDx); dedv = dedDv; /* V */ dedw = dedDw; /* V */ dedx = dedDx; /* V */ dedu = Neg(Add(Add(dedDv,dedDw),dedDx)); } } term; void EangleAux(f,a,b: r4_t; double *eterm; VAR dedf,deda,dedb: r4_t; ) /* compute the derivative of the orthogonal vectors "f" and "g" where "f== s - Proj(s,r)" and "g == r". */ VAR dedr,deds: r4_t; { ??? m = r4_dot(f,f)+Epsilon; /* S */ ??? u = r4_dot(f,a); /* S */ ??? v = r4_dot(f,b); /* S */ ??? U = u/m; /* S */ ??? V = v/m; /* S */ ??? Uf = r4_Scale(U,f); /* V */ ??? Vf = r4_Scale(V,f); /* V */ ??? R = r4_Sub(a,Uf); /* V */ ??? S = r4_Sub(b,Vf); /* V */ { Eangle(R,S,eterm,dedr,deds); ??? dedV = - Dot(deds,f); /* S */ ??? dedU = - Dot(dedr, f); /* S */ ??? dedu = dedU/m; /* S */ ??? dedv = dedV/m; /* S */ ??? dedm = (-1.0/m) * (dedU*U + dedV*V); /* S */ ??? dedm2 = r4_Scale(2.0,f); /* S */ ??? dedm2f = r4_Scale(dedm, dedm2); /* V */ ??? dedua = r4_Scale(dedu, a); /* V */ ??? dedvb = r4_Scale(dedv, b); /* V */ ??? dedrU = r4_Neg(r4_Scale(U, dedr)); /* V */ ??? dedsV = r4_Neg(r4_Scale(V, deds)); /* V */ ??? t1 = r4_Add(dedm2f,dedua); /* V */ ??? t2 = r4_Add(t1, dedvb); /* V */ ??? t3 = r4_Add(t2, dedrU); /* V */ ??? t4 = r4_Add(t3, dedsV); /* V */ ??? deduf = r4_Scale(dedu, f); /* V */ ??? dedvf = r4_Scale(dedv, f); /* V */ ??? c1 = r4_Add(deduf, dedr); /* V */ ??? d1 = r4_Add(dedvf, deds); /* V */ { dedf = t4; deda = c1; dedb = d1; } } } EangleAux; void Eangle( *R,S: r4_t; double *E; VAR EDR,EDS: r4_t; ) /* Given two vectors "R" and "S" compute the "cos" of the angle between the vectors, the curvature term and the derivatives of energy respect to the two vectors: eeDR and eeDS. */ { ??? m = r4_Norm(R) + Epsilon; ??? n = r4_Norm(S) + Epsilon; ??? o = r4_dot(R, S); ??? d = m*n; ??? q = o/d; { if (d!=0.0) { E = K * (1.0 + q); if (grad) { ??? eDq = 1.0 * K; ??? eDo = eDq / d; ??? eDd = - eDq * q / d; ??? eDm = eDd * n; ??? eDn = eDd * m; { EDR = r4_Mix(eDo, S, eDm/m, R); EDS = r4_Mix(eDo, R, eDn/n, S); } } } } } Eangle; { /* Initialize */ for (i = 0; i < NV; i++){ eDc[i] = zero; } /* Compute energy "e", and the gradient "eDr": */ e = 0.0; for (i = 0; i < num.nre; i++) { for (j = 0; j < num.nce; j++) { for (k = j+1; k < num.nce; k++) { if ((ChilWall[i,j]->exists) && (ChilWall[i,k]->exists)) { if ((Adjacent(ChilWall[i,j], ChilWall[i,k]))) { ??? u1 = OrgV(ChilWall[i,j].pa)->num; ??? v1 = OrgV(NextE (ChilWall[i,j].pa))->num; ??? w1 = OrgV(PrevE(ChilWall[i,j].pa))->num; ??? u2 = OrgV(ChilWall[i,k].pa)->num; ??? v2 = OrgV(NextE (ChilWall[i,k].pa))->num; ??? w2 = OrgV(PrevE(ChilWall[i,k].pa))->num; { if ((v1 == v2) && (u1 == w2)) { AddTerm(v1,u1,w1,u2); } else if ((v1 == w2) && (u1 == u2)){ AddTerm(v1,u1,w1,v2); } else if ((v1 == u2) && (u1 == v2)){ AddTerm(v1,u1,w1,w2); } else if ((u1 == v2) && (w1 == w2)){ AddTerm(u1,w1,v1,u2); } else if ((u1 == w2) && (w1 == u2)){ AddTerm(u1,w1,v1,v2); } else if ((u1 == u2) && (w1 == v2)){ AddTerm(u1,w1,v1,w2); } else if ((w1 == v2) && (v1 == w2)){ AddTerm(w1,v1,u1,u2); } else if ((w1 == w2) && (v1 == u2)){ AddTerm(w1,v1,u1,v2); } else if ((w1 == u2) && (v1 == v2)){ AddTerm(w1,v1,u1,w2); } else if ((v1 == w2) && (u1 == v2)){ AddTerm(v1,u1,w1,u2); } else if ((v1 == v2) && (u1 == u2)){ AddTerm(v1,u1,w1,w2); } else if ((v1 == u2) && (u1 == w2)){ AddTerm(v1,u1,w1,v2); } else if ((u1 == w2) && (w1 == v2)){ AddTerm(u1,w1,v1,u2); } else if ((u1 == v2) && (w1 == u2)){ AddTerm(u1,w1,v1,w2); } else if ((u1 == u2) && (w1 == w2)){ AddTerm(u1,w1,v1,v2); } else if ((w1 == w2) && (v1 == v2)){ AddTerm(w1,v1,u1,u2); } else if ((w1 == v2) && (v1 == u2)){ AddTerm(w1,v1,u1,w2); } else if ((w1 == u2) && (v1 == w2)){ AddTerm(w1,v1,u1,v2); } } } } } } } } } } /* END Eval */ bool_t Adjacent(f1,f2: Wall) count : INTEGER = 0; { ??? u1 = OrgV(f1.pa)->num; ??? v1 = OrgV(NextE (f1.pa))->num; ??? w1 = OrgV(PrevE(f1.pa))->num; ??? u2 = OrgV(f2.pa)->num; ??? v2 = OrgV(NextE (f2.pa))->num; ??? w2 = OrgV(PrevE(f2.pa))->num; { if ((u1 == u2) || (u1 == v2) || (u1 == w2)){ count = count + 1; } if ((v1 == u2) || (v1 == v2) || (v1 == w2)){ count = count + 1; } if ((w1 == u2) || (w1 == v2) || (w1 == w2)){ count = count + 1; } if (count == 2){ return TRUE; } else { return FALSE; } } } /* END Adjacent */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Curv2D()" } /* END Name */ { } Curvature2D. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/OriKamSpring.c /* See {OriKamSpring.h} */ // #INCLUDE /* In this module non exists an Apropiate factor normalization for this energy, actually it is 0.5. Revisions: 18-11-2000: Added the constant value Epsilon to avoid possiblev infinite values (Nan). */ #include #include // #INCLUDE #include // #INCLUDE CONST Epsilon == 1.0d-10; TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; AdjMatrix == ARRAY OF double_vec_t; double inf = Math.pow(10.0,10.0); VAR REVEAL T == Public BRANDED OBJECT double F; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ termVar: REF bool_vec_t; /* TRUE if node is variable & existing */ m: REF AdjMatrix; /* Matrix of initial distances */ eDdif: REF double_vec_t_vec_t; /* (Work) Gradient of "e" rel. to "dif" */ double L; /* Kamada' constant */ l,k: REF AdjMatrix; /* parameters: lij is the original length of the spring between pi and pj; kij is the strength of the spring pi and pj. */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) double *dmax; { ??? NV = top->node.ne; ??? length = ((double)erg->length); ??? strength = ((double)erg->strength); { erg->m = MakeAdjMatrix(top); ShortestPath(erg->m, NV); if (erg->detail) { PrintHalfMatrix(erg->m, NV); } dmax = FindMaxDistance(erg->m, NV); erg->L = length/dmax; erg->F = 0.50; erg->top = top; erg->termVar = bool_vec_new(NV); erg->eDdif = double_vec_t_vec_new(NV, NV); erg->l = CalculateLength (erg->m, NV, erg->L); erg->k = CalculateStrengh(erg->m, NV, strength); if (erg->detail) { PrintHalfMatrix(erg->k, NV); } /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->termVar^[i] = FALSE; } } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decides which nodes are relevant to kamada energy. A node is relevant iff it is variable. */ ??? NV = erg->top->node.ne; ??? termVar = erg->termVar^; { /* Find the relevant nodes: */ assert((variable.ne) == NV); for (v = 0; v < NV; v++) { termVar[v] = variable[v]; } } } /* END DefVar */ AdjMatrix *MakeAdjMatrix(ElemTableRec_t *top, )== REF ARRAY OF double_vec_t m ; v: REF ARRAY OF INTEGER; { m = NEW(REF ARRAY OF double_vec_t, top->node.ne, top->node.ne); for (i = 0; i < top->node.ne; i++) { for (j = 0; j < top->node.ne; j++) { m[i,j] = inf; } } for (i = 0; i < top->node.ne; i++) { ??? a = top->node[i]; ??? star = Triangulation.Neighbors(OrgV(a),top); ??? nv = ((star^).ne); { m[i,i] = 0.0; v = NEW(REF ARRAY OF INTEGER, nv); for (k = 0; k < nv; k++) { v[k] = star[k]->num; m[i,v[k]] = 1.0; m[v[k],i] = 1.0; } } } return m; } /* END MakeAdjMatrix */ double FindMaxDistance( *m: REF AdjMatrix; INTEGER n; ) max = 0.0; { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] > max) { max = m[i,j]; } } } return max; } /* END FindMaxDistance */ AdjMatrix *CalculateStrengh( *m : REF AdjMatrix; INTEGER n; double K; )== REF ARRAY OF double_vec_t k ; { k = NEW(REF ARRAY OF double_vec_t, n, n); for (i = 0; i < n; i++) { for (j = 0; j <= (i); j++) { if (i == j ){ k[i,j] = 0.0; } else { k[i,j] = K / (m[i,j]*m[i,j]); k[j,i] = k[i,j]; } } } return k; } /* END CalculateStrengh */ AdjMatrix *CalculateLength( *m : REF AdjMatrix; INTEGER n; double L; )== REF ARRAY OF double_vec_t l ; { l = NEW(REF ARRAY OF double_vec_t, n, n); for (i = 0; i < n; i++) { for (j = 0; j <= (i); j++) { l[i,j] = L * m[i,j]; l[j,i] = l[i,j]; } } return l; } /* END CalculateLength */ /* UNUSED */ void PrintAdjMatrix(*m : REF AdjMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.LongReal(m[i,j]) & " "); } } fprintf(stderr, "\n"); } } /* END PrintAdjMatrix */ void PrintHalfMatrix(*m : REF AdjMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.LongReal(m[i,j],Fmt.Style.Fix,prec=3) & " "); } } fprintf(stderr, "\n"); } } /* END PrintHalfMatrix */ void ShortestPath(VAR m : REF AdjMatrix; n : INTEGER) double *s; { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] < inf) { for (k = 0; k < n; k++) { if (m[i,k] < inf) { s = m[j,i] + m[i,k]; if (s < m[j,k]){ m[j,k] = s; } } } } } } } /* END ShortestPath */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { ??? NV = erg->top->node.ne; ??? F = erg->F; ??? eDdif = erg->eDdif^; ??? termVar = erg->termVar; ??? k = erg->k^; ??? l = erg->l^; { void AccumTerm(*u: uint) /* Adds to "e" the energy term corresponding to a node "u". Returns also the gradient "eDdif". */ { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? cv = c[i]; ??? n = r4_Sub(cu,cv); ??? dif = r4_Norm(n); ??? luv = l[u,i]; ??? kuv = k[u,i]; ??? d = dif - luv; ??? d2 = d * d; { e = e + F * kuv * d2; if (grad) { eDdif[u,i] = 2.0 * F * kuv * d; eDdif[i,u] = eDdif[u,i]; } else { eDdif[u,i] = 0.0; eDdif[i,u] = eDdif[u,i]; } } } } } AccumTerm; void Distribute_eDdif(*u: uint) /* Distribute eDdif on endpoints "c[u]" and "c[v]" */ { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? ci = c[i]; ??? n = r4_Sub(cu, ci); ??? dif = r4_Norm(n)+Epsilon; ??? eDi = eDc[i]; ??? eDu = eDc[u]; ??? difDcu = r4_Scale(1.0/dif, n); ??? difDci = r4_Scale(-1.0/dif,n); ??? eDcu = r4_Scale(eDdif[u,i], difDcu); ??? eDci = r4_Scale(eDdif[u,i], difDci); { if (termVar[i]) { eDi = r4_Add(eDi, eDci); } if (termVar[u]) { eDu = r4_Add(eDu, eDcu); } } } } } Distribute_eDdif; { for (i = 0; i < NV; i++){ eDc[i]=(r4_t){0.0, 0.0, 0.0, 0.0}; } e = 0.0; for (l = 0; l < NV; l++) { if (termVar[l]) { AccumTerm(l); if (grad) { Distribute_eDdif(l); } } } } } } Eval; char * SELF_Name(SELF_T *erg)== { return "OriKamada(ilenth = " & Fmt.Real(erg->length,Fmt.Style.Fix,prec = 3) \ " istrength = " & Fmt.Real(erg->strength,Fmt.Style.Fix,prec= 3) & ")"; } /* END Name */ { } OriKamSpring. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/OrientationEnergy.c /* See {OrientationEnergy.h} */ // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE TYPE bool_vec_t == ARRAY OF bool_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ polyRelevant: REF bool_vec_t; /* TRUE if cell is relevant */ tetra : REF Place_vec_t; /* Tetrahedra with consistent orientations */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0/((double)top->cell.ne); erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->polyRelevant = bool_vec_new(top->cell.ne); /* Collect cells with consistent orientation */ erg->tetra = Triangulation.CollectTetrahedra(top); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->cell.ne; i++){ erg->polyRelevant[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which cells are relevant to "Orientation" energy. A cell is relevant iff it has at least one variable corner. */ int NV = erg->top->node.ne; ??? NP = erg->top->cell.ne; bool_vec_t vVar = erg->vVar^; ??? t = erg->tetra^; ??? polyRelevant = erg->polyRelevant^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant cells: */ for (i = 0; i < NP; i++){ polyRelevant[i] = FALSE; } for (i = 0; i < NP; i++) { assert(Pneg(t[i])->num == i); ??? a = t[i]; Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); Node_t w = OrgV(PrevE(a)); Node_t x = OrgV(PrevE(PrevF(a))); Wall_t f1 = PWall(a); Wall_t f2 = PWall(PrevF(a)); Wall_t f3 = PWall(PrevF(NextE(a))); Wall_t f4 = PWall(PrevF(PrevE(a))); { assert(f1 != f2) && (f2 != f3) && (f3 != f4); polyRelevant[i] = vVar.e[u->num]) || (vVar.e[v->num]) || (vVar.e[w->num]) || (vVar.e[x->num]; } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) double *eterm,etermDdet; { int NV = erg->top->node.ne; ??? NP = erg->top->cell.ne; ??? t = erg->tetra^; ??? vVar = erg->vVar^; ??? polyRelevant = erg->polyRelevant^; ??? K = erg->K; ??? minDet = erg->minVol * 6.0; { double ComputeDet(*U, V, W, X: uint) /* Compute the determinat of the tetrahedron "u v w x" in R^{3}. */ { ??? pu = c[U]; ??? pv = c[V]; ??? pw = c[W]; ??? px = c[X]; ??? a = (r4_t){pu[0], pu[1], pu[2], 1.0}; ??? b = (r4_t){pv[0], pv[1], pv[2], 1.0}; ??? c = (r4_t){pw[0], pw[1], pw[2], 1.0}; ??? d = (r4_t){px[0], px[1], px[2], 1.0}; { return r4_det(a,b,c,d); } } ComputeDet; void Compute_e_from_det(det: double; double eterm; VAR VAR etermDdet: double) /* Returns in "eterm" the energy term corresponding to a cell with determinant "det". Also, if "grad" is true, stores in "etermDdet" the derivative of that term. */ { if (det >= minDet) { eterm = 0.0; etermDdet = 0.0 } else { ??? h = det/minDet-1.0; ??? f = h*h; { eterm = K * f; if (grad) { ??? hDdet = 1.0/minDet; ??? fDdet = 2.0 * h * hDdet; { etermDdet = K * fDdet; } } else { etermDdet = 0.0; } } } } Compute_e_from_det; void Distribute_eDdet( uint *iu,iv,iw,ix; etermDdet: double) /* Accumulates in "eDc" the gradient of "eterm" relative to the corners of the tetrahedron "iu iv iw ix", given the derivative "etermDdet" of "eterm" relative to the tetrahedron's determinant "det". */ { ??? pu = c[iu]; ??? pv = c[iv]; ??? pw = c[iw]; ??? px = c[ix]; ??? pu0 = pu[0], pu1 = pu[1], pu2 = pu[2], double pv0 = pv[0], pv1 = pv[1], pv2 = pv[2]; double pw0 = pw[0], pw1 = pw[1], pw2 = pw[2]; double px0 = px[0], px1 = px[1], px2 = px[2]; double detwx23 = pw2 - px2; double detwx13 = pw1 - px1; double detwx12 = pw1 * px2 - px1 * pw2; double detwx03 = pw0 - px0; double detwx02 = pw0 * px2 - px0 * pw2; double detwx01 = pw0 * px1 - px0 * pw1; double detvx23 = pv2 - px2; double detvx13 = pv1 - px1; double detvx12 = pv1 * px2 - px1 * pv2; double detvx03 = pv0 - px0; double detvx02 = pv0 * px2 - px0 * pv2; double detvx01 = pv0 * px1 - px0 * pv1; double detvw23 = pv2 - pw2; double detvw13 = pv1 - pw1; double detvw12 = pv1 * pw2 - pw1 * pv2; double detvw03 = pv0 - pw0; double detvw02 = pv0 * pw2 - pw0 * pv2; double detvw01 = pv0 * pw1 - pw0 * pv1; double detDu0 = + pv1 * detwx23 - pv2 * detwx13 + detwx12; double detDu1 = - pv0 * detwx23 + pv2 * detwx03 - detwx02; double detDu2 = + pv0 * detwx13 - pv1 * detwx03 + detwx01; double detDv0 = - pu1 * detwx23 + pu2 * detwx13 - detwx12; double detDv1 = + pu0 * detwx23 - pu2 * detwx03 + detwx02; double detDv2 = - pu0 * detwx13 + pu1 * detwx03 - detwx01; double detDw0 = + pu1 * detvx23 - pu2 * detvx13 + detvx12; double detDw1 = - pu0 * detvx23 + pu2 * detvx03 - detvx02; double detDw2 = + pu0 * detvx13 - pu1 * detvx03 + detvx01; double detDx0 = - pu1 * detvw23 + pu2 * detvw13 - detvw12; double detDx1 = + pu0 * detvw23 - pu2 * detvw03 + detvw02; double detDx2 = - pu0 * detvw13 + pu1 * detvw03 - detvw01; double eDu0 = etermDdet * detDu0; double eDu1 = etermDdet * detDu1; double eDu2 = etermDdet * detDu2; double eDv0 = etermDdet * detDv0; double eDv1 = etermDdet * detDv1; double eDv2 = etermDdet * detDv2; double eDw0 = etermDdet * detDw0; double eDw1 = etermDdet * detDw1; double eDw2 = etermDdet * detDw2; double eDx0 = etermDdet * detDx0; double eDx1 = etermDdet * detDx1; double eDx2 = etermDdet * detDx2; { if (vVar.e[iu]) { eDc[iu,0] = eDc[iu,0] + eDu0; eDc[iu,1] = eDc[iu,1] + eDu1; eDc[iu,2] = eDc[iu,2] + eDu2; } if (vVar.e[iv]) { eDc[iv,0] = eDc[iv,0] + eDv0; eDc[iv,1] = eDc[iv,1] + eDv1; eDc[iv,2] = eDc[iv,2] + eDv2; } if (vVar.e[iw]) { eDc[iw,0] = eDc[iw,0] + eDw0; eDc[iw,1] = eDc[iw,1] + eDw1; eDc[iw,2] = eDc[iw,2] + eDw2; } if (vVar.e[ix]) { eDc[ix,0] = eDc[ix,0] + eDx0; eDc[ix,1] = eDc[ix,1] + eDx1; eDc[ix,2] = eDc[ix,2] + eDx2; } } } Distribute_eDdet; { e = 0.0; /* Clear gradient accumulators */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, ..}; } /* Enumerate cells and compute cell determinants: */ for (j = 0; j < NP; j++) { if (polyRelevant[j]) { ??? a = t[j]; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(PrevF(a)))->num; ??? det = ComputeDet(un, vn, wn, xn); { Compute_e_from_det(det, eterm, etermDdet); /* fprintf(stderr, Fmt.LongReal(det) & " " & Fmt.LongReal(eterm) \ " " & Fmt.LongReal(etermDdet) & "\n"); VAR c: char *; { if (det < 0.0){ c = "-" }else{ c= "+"; } fprintf(stderr, c); } */ e = e + eterm; if (grad) { Distribute_eDdet(un, vn, wn, xn, etermDdet) } } } } /*fprintf(stderr, "###\n");*/ } } } /* END Eval */ PROCEDURE Name(erg: T) : char *== { return "Orient(" \ "minVol = " & Fmt.LongReal(erg->minVol,Fmt.Style.Fix,prec = 6) \ ")" } /* END Name */ { } OrientationEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/OriginalCurvature3D.c /* See {OriginalCurvature3D.h} */ // #INCLUDE #define OriginalCurvature3D_C_author \ "Created by L.A.P.Lozada.\n" \ "Modified by L.A.P.Lozada on 2000-05-04." #include // #INCLUDE // #INCLUDE CONST zero == (r4_t){0.0,0.0,0.0,0.0}; TYPE bool_vec_t == ARRAY OF bool_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ bool_vec_t wallRelevant; /* TRUE if wall is relevant */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0; erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->wallRelevant = bool_vec_new(top->wall.ne); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar.e[i] = FALSE; } for (i = 0; i < top->wall.ne; i++){ erg->wallRelevant.e[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which wall are relevant to the curvature energy. A wall is relevant iff has exactly two cell incident to it. */ int NV = erg->top->node.ne; int NF = erg->top->wall.ne; bool_vec_t vVar = erg->vVar^; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant walls: */ for (i = 0; i < NF; i++){ wallRelevant.e[i] = FALSE; } for (i = 0; i < NF; i++) { ??? f = wall[i]; ??? a = f.pa; ??? p1 = Pneg(a); ??? p2 = Ppos(a); { if (((p1!=NULL) && (p2!=NULL))) { wallRelevant.e[i] = TRUE; } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) CONST eps == 0.0; { int NV = erg->top->node.ne; int NF = erg->top->wall.ne; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; ??? K = erg->K; ??? vVar = erg->vVar^; { void AddTerm(*iu,iv,iw,ix,iy: uint) /* Adds one term of the curvature energy to "e" (and its derivative to "eDc, if "grad" is TRUE). The terms correspond to the wall "f == u v w" shared by the tetrahedra "u v w x" (Pneg) and "u v w y" (Ppos). _ _ |\ w w /| \ /|\ /|\ / \ / | \ / | \ / / | \ / | \ / | \ / | \ x /____|____\v v/____|____\ y \ | f / \ f | / \ | / \ | / \ | / \ | / \ | / \ | / \|/ \|/ u u Pneg Ppos */ double eterm ; eDdu, eDdv, eDdw, eDdx, eDdy: r4_t; { ??? u = c[iu]; ??? v = c[iv]; ??? w = c[iw]; ??? x = c[ix]; ??? y = c[iy]; { term(u,v,w,x,y, eterm, eDdu, eDdv, eDdw, eDdx, eDdy); e = e + eterm; /*fprintf(stderr, Fmt.LongReal(e) & "\n");*/ if (grad) { if (vVar.e[iu]) { eDc[iu] = r4_Add(eDc[iu],eDdu); } if (vVar.e[iv]) { eDc[iv] = r4_Add(eDc[iv],eDdv); } if (vVar.e[iw]) { eDc[iw] = r4_Add(eDc[iw],eDdw); } if (vVar.e[ix]) { eDc[ix] = r4_Add(eDc[ix],eDdx); } if (vVar.e[iy]) { eDc[iy] = r4_Add(eDc[iy],eDdy); } } } } AddTerm; void term(u,v,w,x,y: r4_t; double *eterm; VAR dedu,dedv,dedw,dedx,dedy: r4_t; ) VAR dedDv,dedDw,dedDx,dedDy: r4_t; { r4_t Dv = r4_Sub(v, u); /* V */ r4_t Dw = r4_Sub(w, u); /* V */ r4_t Dx = r4_Sub(x, u); /* V */ r4_t Dy = r4_Sub(y, u); /* V */ { Eangle(Dv,Dw,Dx,Dy, eterm, dedDv,dedDw,dedDx,dedDy); dedv = dedDv; /* V */ dedw = dedDw; /* V */ dedx = dedDx; /* V */ dedy = dedDy; /* V */ dedu = Neg(Add(Add(Add(dedDv,dedDw),dedDx),dedDy)); } } term; void Eangle(r,s,a,b: r4_t; double *eterm; VAR dedr,deds,deda,dedb: r4_t; ) /* compute the derivative of the orthogonal vectors "f" and "g" where "f== s - Proj(s,r)" and "g == r". */ VAR dedf,dedg: r4_t; { ??? m = Dot(r,r); /* S */ ??? n = Dot(r,s); /* S */ ??? m2 = m * m; /* S */ ??? q = n/m; /* S */ ??? qr = Scale(q,r); /* V */ ??? f = Sub(s,qr); /* V */ ??? g = r; /* V */ ??? /* Now, "f" and "g" are orthogonal */ { EangleAux(f,g,a,b,eterm,dedf,dedg,deda,dedb); ??? dedq = -r4_dot(dedf,r); /* S */ ??? dedn = dedq/m; /* S */ ??? dedm = -dedq * (n/m2); /* S */ ??? r2 = r4_Scale(2.0,r); /* V */ ??? v1 = r4_Scale(dedm, r2); /* V */ ??? v2 = r4_Scale(dedn, s); /* V */ ??? v3 = r4_Scale(-q , dedf); /* V */ ??? v4 = dedg; /* V */ ??? v12 = r4_Add(v1,v2); /* V */ ??? v123 = r4_Add(v12,v3); /* V */ ??? v1234= r4_Add(v123,v4); /* V */ ??? dednr = r4_Scale(dedn, r); /* V */ { dedr = v1234; deds = Add(dednr, dedf); } } } Eangle; void EangleAux(f,g,a,b: r4_t; double *eterm; VAR dedf,dedg,deda,dedb: r4_t; ) /* compute the derivative of the orthogonal vectors "f" and "g" where "f== s - Proj(s,r)" and "g == r". */ VAR dedr,deds: r4_t; { ??? m = r4_dot(f,f); /* S */ ??? n = r4_dot(g,g); /* S */ ??? u = r4_dot(f,a); /* S */ ??? v = r4_dot(f,b); /* S */ ??? x = r4_dot(g,a); /* S */ ??? y = r4_dot(g,b); /* S */ ??? U = u/m, /* S */ ??? V = v/m; /* S */ ??? X = x/n; /* S */ ??? Y = y/n; /* S */ ??? Uf = r4_Scale(U,f); /* V */ ??? Xg = r4_Scale(X,g); /* V */ ??? Vf = r4_Scale(V,f); /* V */ ??? Yg = r4_Scale(Y,g); /* V */ ??? UfXg = r4_Neg(r4_Add(Uf,Xg)); /* V */ ??? VfYg = r4_Neg(r4_Add(Vf,Yg)); /* V */ ??? R = r4_Add(a,UfXg); /* V */ ??? S = r4_Add(b,VfYg); /* V */ { EangleVec(R,S,eterm,dedr,deds); ??? dedY = - Dot(deds,g); /* S */ ??? dedX = - Dot(dedr, g); /* S */ ??? dedV = - Dot(deds, f); /* S */ ??? dedU = - Dot(dedr, f); /* S */ ??? dedx = dedX/n; /* S */ ??? dedy = dedY/n; /* S */ ??? dedu = dedU/m; /* S */ ??? dedv = dedV/m; /* S */ ??? dedm = (-1.0/m) * (dedU*U + dedV*V); /* S */ ??? dedn = (-1.0/n) * (dedX*X + dedY*Y); /* S */ ??? dedm2 = r4_Scale(2.0,f); /* S */ ??? dedm2f = r4_Scale(dedm, dedm2); /* V */ ??? dedua = r4_Scale(dedu, a); /* V */ ??? dedvb = r4_Scale(dedv, b); /* V */ ??? dedrU = r4_Neg(r4_Scale(U, dedr)); /* V */ ??? dedsV = r4_Neg(r4_Scale(V, deds)); /* V */ ??? t1 = r4_Add(dedm2f,dedua); /* V */ ??? t2 = r4_Add(t1, dedvb); /* V */ ??? t3 = r4_Add(t2, dedrU); /* V */ ??? t4 = r4_Add(t3, dedsV); /* V */ ??? g2 = r4_Scale(2.0,g); /* S */ ??? dedn2g = r4_Scale(dedn, g2); /* V */ ??? dedxa = r4_Scale(dedx, a); /* V */ ??? dedyb = r4_Scale(dedy, b); /* V */ ??? dedrX = r4_Neg(r4_Scale(X, dedr)); /* V */ ??? dedsY = r4_Neg(r4_Scale(Y, deds)); /* V */ ??? f1 = r4_Add(dedn2g,dedxa); /* V */ ??? f2 = r4_Add(f1, dedyb); /* V */ ??? f3 = r4_Add(f2, dedrX); /* V */ ??? f4 = r4_Add(f3, dedsY); /* V */ ??? deduf = r4_Scale(dedu, f); /* V */ ??? dedxg = r4_Scale(dedx, g); /* V */ ??? dedvf = r4_Scale(dedv, f); /* V */ ??? dedyg = r4_Scale(dedy, g); /* V */ ??? c1 = r4_Add(deduf, dedxg); /* V */ ??? c2 = r4_Add(c1, dedr); /* V */ ??? d1 = r4_Add(dedvf, dedyg); /* V */ ??? d2 = r4_Add(d1, deds); /* V */ { dedf = t4; dedg = f4; deda = c2; dedb = d2; } } } EangleAux; void EangleVec( *R,S: r4_t; double *E; VAR EDR,EDS: r4_t; ) /* Given two vectors "R" and "S" compute the "cos" of the angle between the vectors, the curvature term and the derivatives of energy respect to the two vectors: eeDR and eeDS. */ { ??? m = r4_Norm(R) + eps; ??? n = r4_Norm(S) + eps; ??? o = r4_dot(R, S); ??? d = m*n; ??? q = o/d; { if (d!=0.0) { E = K * (1.0 + q); if (grad) { ??? eDq = 1.0 * K; ??? eDo = eDq / d; ??? eDd = - eDq * q / d; ??? eDm = eDd * n; ??? eDn = eDd * m; { EDR = r4_Mix(eDo, S, eDm/m, R); EDS = r4_Mix(eDo, R, eDn/n, S); } } } } } EangleVec; { /* Initialize */ for (i = 0; i < NV; i++){ eDc[i] = zero; } /* Compute energy "e", and the gradient "eDr": */ e = 0.0; for (i = 0; i < NF; i++) { if (wallRelevant.e[i]) { ??? f = wall[i]; ??? a = f.pa; ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; { assert(xn!=yn); AddTerm(un,vn,wn,xn,yn) } } } } } } /* END Eval */ PROCEDURE Name(/* UNUSED */ erg: T): char *== { return "Curv3D()" } /* END Name */ { } Curvature3D. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ParseEnergyParams.c /* See {ParseEnergyParams.h} */ // #INCLUDE #include #include // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE MixedEnergy.T PROCEDURE Parse(argparser_t *pp)/* Raises {ParseParams.Error} */ == CONST MaxTerms == 10; e: ARRAY [0..MaxTerms-1] OF Energy.T; w: ARRAY [0..MaxTerms-1] OF REAL; uint n = 0; { while (argparser_keyword_present(pp, "-energy")){ w[n] = pp.getNextReal(0.0, 1000000000.0); if ((pp.testNext("Excen"))) { e[n] = NEW(ExcenEnergy.T).init(); } else if ((pp.testNext("Curv1D"))){ e[n] = NEW(Curvature1D.T).init(); } else if ((pp.testNext("Curv2D"))){ e[n] = NEW(Curvature2D.T).init(); } else if ((pp.testNext("Curv3D"))){ e[n] = NEW(Curvature3D.T) } else if ((pp.testNext("Spring"))){ if ((pp.testNext("OriKamada"))) { REAL length ; REAL strength; bool_t detail = FALSE; { if ((pp.testNext("strength"))) { strength = pp.getNextReal(0.0, 100000.0); } else { strength = 1.0; } if ((pp.testNext("length"))) { length = pp.getNextReal(0.0, 100000.0); } else { length = 2.0; } if ((pp.testNext("detail"))) { detail = TRUE; } else { detail = FALSE; } e[n] = NEW(OriKamSpring.T,strength=strength, length=length, detail=detail); } }; if ((pp.testNext("ModKamada"))) { REAL length ; REAL strength; { if ((pp.testNext("strength"))) { strength = pp.getNextReal(0.0, 10.0); } else { strength = 1.0; } if ((pp.testNext("length"))) { length = pp.getNextReal(0.0, 10.0); } else { length = 2.0; } e[n] = NEW(ModKamSpring.T,strength=strength, length=length); } }; if ((pp.testNext("VarKamada"))) { REAL length ; REAL strength; { if ((pp.testNext("strength"))) { strength = pp.getNextReal(0.0, 10.0); } else { strength = 1.0; } if ((pp.testNext("length"))) { length = pp.getNextReal(0.0, 10.0); } else { length = 2.0; } e[n] = NEW(VarKamSpring.T,strength=strength, length=length); } }; if ((pp.testNext("Simple"))) { REAL length ; { if ((pp.testNext("length"))) { length = pp.getNextReal(0.0, 10.0); } else { length = 1.0; } e[n] = NEW(SimpleSpring.T,length = length); } }; } else if ((pp.testNext("Spring"))){ REAL *length; { if ((pp.testNext("length"))) { length = pp.getNextReal(0.0, 10.0); } else { length = 1.0; } e[n] = NEW(SimpleSpring.T, length = length) } } else if ((pp.testNext("Orien"))){ double *minVol; { if ((pp.testNext("minVol"))) { minVol = pp.getNextLongReal(); } else { minVol = 1.0/sqrt(72.0); } e[n] = NEW(OrientationEnergy.T) }; } else { argparser_error(pp, "Unknown energy: \"" & argparser_get_next(pp) & "\"") } if (w[n]!=0.0){ n++; } } /* DF energy: */ if (n == 0) { return NULL; } else { return NEW(MixedEnergy.T).init(SUBARRAY(e, 0, n), SUBARRAY(w, 0, n)) } } /* END Parse */ { } ParseEnergyParams. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ParseMinimizerParams.c /* See {ParseMinimizerParams.h} */ // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE Minimizer.T PROCEDURE Parse(argparser_t *pp)/* Raises {ParseParams.Error} */ { if ((argparser_keyword_present(pp, "-minimizer"))){ if ((pp.testNext("Grad"))) { VAR i: Integrator.T; { if ((pp.testNext("RKF4"))) { i = NEW(RKF4Integrator.T) } else if ((pp.testNext("Euler"))){ i = NEW(EulerIntegrator.T) } else { i = NEW(RKF4Integrator.T) } return NEW(GradMinimizer.T).setIntegrator(i); } } else if ((pp.testNext("Coord"))){ VAR i: UniMin.T; n: uint; { if ((pp.testNext("Brent"))) { i = NEW(BrentUniMin.T); } else if ((pp.testNext("JS"))){ i = NEW(JSUniMin.T) } else { i = NEW(BrentUniMin.T) } if ((pp.testNext("budget"))) { n = argparser_get_next_int(pp, 5, 100) } else { n = 7 } return NEW(CoordMinimizer.T).setUniMin(i).setBudget(n); } /* } else if ((pp.testNext("Waltz"))){ double *l; { if ((pp.testNext("gamma"))) { l = pp.getNextLongReal(0.0, 100.0) } else { l = 1.0; } return NEW(WaltzMinimizer.T).setGamma(l); } } else if ((pp.testNext("Down"))){ double *a,b; { if ((pp.testNext("alpha"))) { a = pp.getNextLongReal(1.00001, 99.99999) } else { a = 3.06956450765297882; } if ((pp.testNext("beta"))) { b = pp.getNextLongReal(0.00001, 0.99999) } else { b = 0.5; } return NEW(DownMinimizer.T).setAlphaBeta(a,b); } */ } else { argparser_error(pp, "Unknown optimization method: " & argparser_get_next(pp)); assert(FALSE); } } else { return NULL } } /* END Parse */ { } ParseMinimizerParams. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/PartialSpring.c /* See {PartialSpring.h} */ // #INCLUDE #define PartialSpring_C_author \ "Modified by L.A.P.Lozada on 2000-11-18." // #INCLUDE #include // #INCLUDE #include // #INCLUDE CONST inf == (uint.ne-1); TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; AdjacencyMatrix == ARRAY OF uint_vec_t; SpringList == ARRAY OF Spring; Spring == RECORD u,v : uint; /* extremities of the spring */; } REVEAL T == Public BRANDED OBJECT ElemTableRec_t *top; /* The map elements. */ termVar: REF bool_vec_t; /* TRUE if node is variable & existing */ m : REF AdjacencyMatrix; /* Matrix of initial distances */ eDdif: REF double_vec_t_vec_t; /* (Work) Gradient of "e" rel. to "dif" */ double L; /* Kamada' constant */ spr : REF SpringList; /* pointer to the list Spring */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) double *dmax; { ??? NV = top->node.ne; { erg->m = MakeAdjacencyMatrix(top); /*PrintHalfMatrix(erg->m, NV);*/ ShortestPath(erg->m, NV); erg->spr = ChooseSprings(erg->m); /*PrintHalfMatrix(erg->m, NV);*/ dmax = FLOAT(FindMaxDistance(erg->m, NV), double); erg->L = FLOAT(erg->length,double)/dmax; erg->top = top; erg->termVar = bool_vec_new(NV); erg->eDdif = double_vec_t_vec_new(NV, NV); /*PrintHalfMatrix(erg->k, NV);*/ /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->termVar^[i] = FALSE; } } } /* END DefTop */ SpringList *ChooseSprings(READOLNY m : AdjacencyMatrix; dmax: uint)== uint ns = 0; uint nu,d; { int NV = (m.ne); ??? rs = NEW(REF SpringList, NV*NV), s == rs^; ??? ok = NEW(REF ARRAY OF bool_t, NV); { /* catch distance less equal to 2 */ for (i = 0; i < NV; i++) { for (j = 0; j < NV; j++) { if ((m[i,j] <= MIN(2,dmax))) { s[ns] = Spring{i,j}; ns++; } } } d = 2; while (d < dmax) { /* find a certain nodes that are distance >= "d" apart */ for (i = 0; i < NV; i++){ ok[i] = TRUE; } for (i = 0; i < NV; i++) { if (ok[i]) { for (j = 0; j < NV; j++) { if (m[i,j] <= d-1){ ok[j] = FALSE; } } } } /* Add spring between those nodes that have a distance less equal to 2*d */ for (i = 0; i < NV; i++) { if (ok[i]) { for (j = 0; j < NV; j++) { if ((ok[j]) && (m[i,j] < 2*d)){ s[ns] = Spring{i,j}; ns++; } } } } d = 2*d; } ??? rr = NEW(REF SpringList, ns); { rr^ = SUBARRAY(s,0,ns); return rr; } } } ChooseSprings; void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which nodes are relevant to kamada energy. A node is relevant iff it is variable. */ int NV = erg->top->node.ne; ??? termVar = erg->termVar^; { /* Find the relevant nodes: */ assert((variable.ne) == NV); for (v = 0; v < NV; v++) { termVar[v] = variable[v]; } } } /* END DefVar */ AdjacencyMatrix *MakeAdjacencyMatrix(ElemTableRec_t *top, )== REF AdjacencyMatrix m ; { m = NEW(REF ARRAY OF uint_vec_t , top->node.ne, top->node.ne); for (i = 0; i < top->node.ne; i++) { for (j = 0; j < top->node.ne; j++) { m[i,j] = inf; } m[i,i] = 0; } for (i = 0; i < top->NE; i++) { ??? a = top->edge[i].pa; Node_t i = OrgV(a)->num; Node_t j = OrgV(Clock(a))->num; { m[i,j] = 1; } } return m; } /* END MakeAdjacencyMatrix */ uint FindMaxDistance( *m: REF AdjacencyMatrix; INTEGER n; ) max = 0; { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] > max) { max = m[i,j]; } } } return max; } /* END FindMaxDistance */ double CalculateStrength(dist : uint) { if (dist == 0){ return 0.0; } else { ??? d = ((double)dist); { return 1.0/(d*d); } } } /* END CalculateStrength */ double CalculateLength(dist : uint) { if (dist == 0){ return 0.0; } else { ??? d = ((double)dist); { return d; } } } /* END CalculateLength */ /* UNUSED */ void PrintAdjacencyMatrix(*m : REF AdjacencyMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.Int(m[i,j]) & " "); } } fprintf(stderr, "\n"); } } /* END PrintAdjacencyMatrix */ /* UNUSED */ void PrintHalfMatrix(*m : REF AdjacencyMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.Int(m[i,j]) & " "); } } fprintf(stderr, "\n"); } } /* END PrintHalfMatrix */ void ShortestPath(VAR m : REF AdjacencyMatrix; n : INTEGER) uint *s; { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] < inf) { for (k = 0; k < n; k++) { if (m[i,k] < inf) { s = m[j,i] + m[i,k]; if (s < m[j,k]){ m[j,k] = s; } } } } } } } ShortestPath; void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? eDdif = erg->eDdif^; ??? termVar = erg->termVar; ??? length = erg->L; ??? strength = ((double)erg->strength); ??? m = erg->m^; { void AccumTerm(*u: uint) /* Adds to "e" the energy term corresponding to a node "u". Returns also the gradient "eDdif". */ CONST Epsilon == 1.0d-10; { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? cv = c[i]; ??? n = r4_Sub(cu,cv); ??? dif = r4_Norm(n); ??? d2 = dif * dif + Epsilon; ??? duv = m[u,i]; ??? luv = length * CalculateLength(duv); ??? kuv = strength * CalculateStrength(duv); ??? l2 = luv * luv + Epsilon; ??? d3 = d2 * dif + Epsilon; { e = e + kuv * ( (d2/l2) + (l2/d2) - 2.0); if (grad) { eDdif[u,i] = 2.0 * kuv * ( (dif/l2) - (l2/d3)); eDdif[i,u] = eDdif[u,i]; } else { eDdif[u,i] = 0.0; eDdif[i,u] = eDdif[u,i]; } } } } } AccumTerm; void Distribute_eDdif(*u: uint) /* Distribute eDdif on endpoints "c[u]" and "c[v]" */ CONST Epsilon == 1.0d-10; { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? ci = c[i]; ??? n = r4_Sub(cu, ci); ??? dif = r4_Norm(n)+Epsilon; ??? eDi = eDc[i]; ??? eDu = eDc[u]; ??? difDcu = r4_Scale(1.0/dif, n); ??? difDci = r4_Scale(-1.0/dif,n); ??? eDcu = r4_Scale(eDdif[u,i], difDcu); ??? eDci = r4_Scale(eDdif[u,i], difDci); { if (termVar[i]) { eDi = r4_Add(eDi, eDci); } if (termVar[u]) { eDu = r4_Add(eDu, eDcu); } } } } } Distribute_eDdif; { for (i = 0; i < NV; i++){ eDc[i]=(r4_t){0.0, 0.0, 0.0, 0.0}; } e = 0.0; for (l = 0; l < NV; l++) { if (termVar[l]) { AccumTerm(l); if (grad) { Distribute_eDdif(l); } } } } } } Eval; char * SELF_Name(SELF_T *erg)== { return "PartialSpring(ilenth = " & Fmt.Real(erg->length,Fmt.Style.Fix,prec = 3) \ " istrength = " & Fmt.Real(erg->strength,Fmt.Style.Fix,prec= 3) & ")"; } /* END Name */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/ProxTetraEnergy.c /* See {ProxTetraEnergy.h} */ // #INCLUDE #define ProxTetraEnergy_C_author \ "Modified by L.A.P.Lozada on 99-08-19." // #INCLUDE // #INCLUDE #include #include /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ TYPE FourNodes_t == RECORD u, v, w, x: uint; } bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; REVEAL T == Public BRANDED OBJECT ElemTableRec_t *top; uint nT; /* Number of tetrahedrons existing on "triang" */ double K; /* Energy normalization factor */ bool_vec_t vVar; /* Which nodes are variable */ quad: REF ARRAY OF FourNodes_t; /* The existing tetrahedrons */ pVar: REF bool_vec_t; /* Which tetrahedrons in "@{chip->?}" are variable */ bar: REF Coords_t; /* (Work) Barycenters of tetrahedrons in "@{chip->?}" */ eDbar: REF Coords_t; /* (Work) Gradient of "e" rel "bar" */ rsq: REF double_vec_t; /* (Work) Nominal tetrahedron radius, squared */ eDrsq: REF double_vec_t; /* (Work) Gradient of "e" rel "rsq" */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->top = top; /* Work areas: */ erg->quad = CollectExistingTetrahedrons(top); erg->NT = ((erg->quad^).ne); erg->K = 1.0/((double)erg->NT*erg->NT); erg->vVar = bool_vec_new(top->node.ne); erg->pVar = bool_vec_new(erg->NT); erg->bar = NEW(REF Coords_t, erg->NT); erg->eDbar = NEW(REF Coords_t, erg->NT); erg->rsq = double_vec_new(erg->NT); erg->eDrsq = double_vec_new(erg->NT); /* In case the client forgets to call "defVar": */ for (i = 0; i < erg->NT; i++){ erg->pVar[i] = TRUE; } } /* END DefTop */ PROCEDURE CollectExistingTetrahedrons(ElemTableRec_t *top): REF ARRAY OF FourNodes_t == NT: uint = 0; { ??? NP = top->cell.ne; ??? t = NEW(REF ARRAY OF FourNodes_t, NP)^; { for (i = 0; i < NP; i++) { ??? p = top->cell[i]; ??? a = Srot(top.cell[i]); { if ((p->exists) && (DegreeOfNode(a) == 4)) { ??? u = p.node[0]; ??? un = NARROW(u, Triangulation.Node); ??? v = p.node[1]; ??? vn = NARROW(v, Triangulation.Node); ??? w = p.node[2]; ??? wn = NARROW(w, Triangulation.Node); ??? x = p.node[3]; ??? xn = NARROW(x, Triangulation.Node); { assert(un->exists) && (vn->exists) && (wn->exists) && (xn->exists); t[NT] = FourNodes_t{u->num, v->num, w->num, x->num} } NT++ } } } ??? r = NEW(REF ARRAY OF FourNodes_t, NT); { r^ = SUBARRAY(t, 0, NT); return r; } } } /* END CollectExistingTetrahedrons */ void SELF_DefVar(SELF_T *erg, *variable: ARRAY OF bool_t) { /* Separate the existing tetrahedrons now in "triang" into the variable list "pVar" and the fixed list "tfix". (A tetrhedron is variable if any of its nodes is variable.) */ ??? NT = erg->NT; int NV = erg->top->node.ne; bool_vec_t vVar = erg->vVar^; ??? quad = erg->quad^; ??? pVar = erg->pVar^; { assert((variable.ne) == NV); vVar = variable; for (i = 0; i < NT; i++) { ??? ti = quad[i]; { pVar[i] = vVar.e[ti.u]) || (vVar.e[ti.v]) || (vVar.e[ti.w]) || (vVar.e[ti.x] } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { ??? NT = erg->NT; int NV = erg->top->node.ne; bool_vec_t vVar = erg->vVar^; ??? quad = erg->quad^; ??? pVar = erg->pVar^; ??? bar = erg->bar^; ??? eDbar = erg->eDbar^; ??? rsq = erg->rsq^; ??? eDrsq = erg->eDrsq^; ??? fuzz = ((double)erg->fuzz); ??? fuzz2 = fuzz*fuzz; ??? K = erg->K; { double Compute_rsq(*t: FourNodes_t) /* Computes the 'radius squared' of "t", actually the mean squared node-barycenter distance */ double r = 0.0; VAR { ??? u = c[t.u]; ??? v = c[t.v]; ??? w = c[t.w]; ??? x = c[t.x]; { ??? uv0 = u[0] - v[0], uw0 = u[0] - w[0], ux0 = u[0] - x[0]; ??? vw0 = v[0] - w[0], vx0 = v[0] - x[0], wx0 = w[0] - x[0]; { r = r + uv0*uv0 + uw0*uw0 + ux0*ux0 + vw0*vw0 + vx0*vx0 + wx0*wx0 } ??? uv1 = u[1] - v[1], uw1 = u[1] - w[1], ux1 = u[1] - x[1]; ??? vw1 = v[1] - w[1], vx1 = v[1] - x[1], wx1 = w[1] - x[1]; { r = r + uv1*uv1 + uw1*uw1 + ux1*ux1 + vw1*vw1 + vx1*vx1 + wx1*wx1 } ??? uv2 = u[2] - v[2], uw2 = u[2] - w[2], ux2 = u[2] - x[2]; ??? vw2 = v[2] - w[2], vx2 = v[2] - x[2], wx2 = w[2] - x[2]; { r = r + uv2*uv2 + uw2*uw2 + ux2*ux2 + vw2*vw2 + vx2*vx2 + wx2*wx2 } ??? uv3 = u[3] - v[3], uw3 = u[3] - w[3], ux3 = u[3] - x[3]; ??? vw3 = v[3] - w[3], vx3 = v[3] - x[3], wx3 = w[3] - x[3]; { r = r + uv3*uv3 + uw3*uw3 + ux3*ux3 + vw3*vw3 + vx3*vx3 + wx3*wx3 } return r/16.0 } } Compute_rsq; void Distribute_eDrsq(*t: FourNodes_t; *eDr2: double) /* Adds to the gradient "eDc" the component due to the influence "eDr2" of the radius squared of "quad" on the energy. */ { ??? eDs = 2.0/16.0*eDr2; ??? u = c[t.u], v = c[t.v], w = c[t.w], x = c[t.x] { if (vVar.e[t.u]) { ??? eDu = eDc[t.u]; { eDu[0] = eDu[0] + eDs * (u[0]-v[0] + u[0]-w[0] + u[0]-x[0]); eDu[1] = eDu[1] + eDs * (u[1]-v[1] + u[1]-w[1] + u[1]-x[1]); eDu[2] = eDu[2] + eDs * (u[2]-v[2] + u[2]-w[2] + u[2]-x[2]); eDu[3] = eDu[3] + eDs * (u[3]-v[3] + u[3]-w[3] + u[3]-x[3]); } } if (vVar.e[t.v]) { ??? eDv = eDc[t.v]; { eDv[0] = eDv[0] + eDs * (v[0]-u[0] + v[0]-w[0] + v[0]-x[0]); eDv[1] = eDv[1] + eDs * (v[1]-u[1] + v[1]-w[1] + v[1]-x[1]); eDv[2] = eDv[2] + eDs * (v[2]-u[2] + v[2]-w[2] + v[2]-x[2]); eDv[3] = eDv[3] + eDs * (v[3]-u[3] + v[3]-w[3] + v[3]-x[3]); } } if (vVar.e[t.w]) { ??? eDw = eDc[t.w]; { eDw[0] = eDw[0] + eDs * (w[0]-v[0] + w[0]-u[0] + w[0]-x[0]); eDw[1] = eDw[1] + eDs * (w[1]-v[1] + w[1]-u[1] + w[1]-x[1]); eDw[2] = eDw[2] + eDs * (w[2]-v[2] + w[2]-u[2] + w[2]-x[2]); eDw[3] = eDw[3] + eDs * (w[3]-v[3] + w[3]-u[3] + w[3]-x[3]); } } if (vVar.e[t.x]) { ??? eDx = eDc[t.x]; { eDx[0] = eDx[0] + eDs * (x[0]-v[0] + x[0]-w[0] + x[0]-u[0]); eDx[1] = eDx[1] + eDs * (x[1]-v[1] + x[1]-w[1] + x[1]-u[1]); eDx[2] = eDx[2] + eDs * (x[2]-v[2] + x[2]-w[2] + x[2]-u[2]); eDx[3] = eDx[3] + eDs * (x[3]-v[3] + x[3]-w[3] + x[3]-u[3]); } } } } Distribute_eDrsq; r4_t Compute_bar(*t: FourNodes_t) r4_t b; VAR { ??? u = c[t.u]; ??? v = c[t.v]; ??? w = c[t.w]; ??? x = c[t.x]; { b[0]= (u[0] + v[0] + w[0] + x[0])/4.0; b[1]= (u[1] + v[1] + w[1] + x[1])/4.0; b[2]= (u[2] + v[2] + w[2] + x[2])/4.0; b[3]= (u[3] + v[3] + w[3] + x[3])/4.0; return b } } Compute_bar; void Distribute_eDbar(*t: FourNodes_t; *eDb: r4_t) /* Adds to the gradient "eDc" the component due to the influence "eDb" of "quad"'s barycenter on the energy. */ { ??? eDs0 = eDb[0]/4.0; ??? eDs1 = eDb[1]/4.0; ??? eDs2 = eDb[2]/4.0; ??? eDs3 = eDb[3]/4.0; { if (vVar.e[t.u]) { ??? eDu = eDc[t.u]; { eDu[0] = eDu[0] + eDs0; eDu[1] = eDu[1] + eDs1; eDu[2] = eDu[2] + eDs2; eDu[3] = eDu[3] + eDs3; } } if (vVar.e[t.v]) { ??? eDv = eDc[t.v]; { eDv[0] = eDv[0] + eDs0; eDv[1] = eDv[1] + eDs1; eDv[2] = eDv[2] + eDs2; eDv[3] = eDv[3] + eDs3; } } if (vVar.e[t.w]) { ??? eDw = eDc[t.w]; { eDw[0] = eDw[0] + eDs0; eDw[1] = eDw[1] + eDs1; eDw[2] = eDw[2] + eDs2; eDw[3] = eDw[3] + eDs3; } } if (vVar.e[t.w]) { ??? eDw = eDc[t.w]; { eDw[0] = eDw[0] + eDs0; eDw[1] = eDw[1] + eDs1; eDw[2] = eDw[2] + eDs2; eDw[3] = eDw[3] + eDs3; } } if (vVar.e[t.x]) { ??? eDx = eDc[t.x]; { eDx[0] = eDx[0] + eDs0; eDx[1] = eDx[1] + eDs1; eDx[2] = eDx[2] + eDs2; eDx[3] = eDx[3] + eDs3; } } } } Distribute_eDbar; void AddTetrahedronPlace_tEnergy(i, j: uint) /* Adds to "e" the electric potential energy between the tetrahedrons "quad[i]" and "quad[j]", from "bar[i], "bar[j]", "rsq[i]", and "rsq[j]". Assumes "i!=j". Also adds to "eDrsq[i]", "eDrsq[j]", "eDbar[i]" and "eDbar[j]" the corresponding derivatives, if the tetrahedrons are variable. */ { ??? bi = bar[i], bj = bar[j]; ??? eDbi = eDbar[i], eDbj = eDbar[j]; ??? si = rsq[i], sj = rsq[j]; ??? eDsi = eDrsq[i], eDsj = eDrsq[j]; ??? vij = r4_Sub(bj, bi); ??? s = si + sj; ??? r2 = r4_NormSqr(vij) + fuzz2 * s; ??? r = sqrt(r2); ??? a = K/r; { e = e + a; if (grad) { ??? aDr = - a/r; ??? aDr2 = aDr * 0.5 / r; ??? aDs = aDr2 * fuzz2; ??? aDvij = r4_Scale(2.0 * aDr2, vij); { if (pVar[i]) { eDsi = eDsi + aDs; eDbi = r4_Sub(eDbi, aDvij) } if (pVar[j]) { eDsj = eDsj + aDs; eDbj = r4_Add(eDbj, aDvij) } } } } } AddTetrahedronPlace_tEnergy; { /* Compute barycenters and 'radius squared' of quad[i], clear derivatives: */ for (i = 0; i < NT; i++) { bar[i] = Compute_bar(quad[i]); rsq[i] = Compute_rsq(quad[i]); if (grad) { eDbar[i] = (r4_t){0.0, 0.0, 0.0, 0.0}; eDrsq[i] = 0.0; } } /* Compute energies and the internal derivatives "eDrsq", "eDbar": */ e = 0.0; for (i = 0; i < NT; i++) { if (pVar[i]) { for (j = 0; j < NT; j++) { if ((i!=j) && ((NOT pVar[j]) || (i < j))) { AddTetrahedronPlace_tEnergy(i, j) } } } } /* Distribute "eDrsq", "eDbar" onto "eDc": */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, 0.0, 0.0, 0.0}; } if (grad) { for (i = 0; i < NT; i++) { if (pVar[i]) { Distribute_eDbar(quad[i], eDbar[i]); Distribute_eDrsq(quad[i], eDrsq[i]); } } } } } } /* END Eval */ char * SELF_Name(SELF_T *erg)== { return "Elect(fuzz = " & Fmt.Real(erg->fuzz, prec = 3) & ")"; } /* END Name */ { } ProxTetraEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/SimpleSpring.c /* See {SimpleSpring.h} */ // #INCLUDE #define SimpleSpring_C_author \ "Modified by L.A.P.Lozada on 2000-11-18." // #INCLUDE #include // #INCLUDE // #INCLUDE TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ termVar: REF bool_vec_t; /* TRUE if node is variable & existing */ @{edge->?}Relevant: REF bool_vec_t; /* TRUE if @{edge->?} is relevant */ eDdif: REF double_vec_t /* (Work) Gradient of "e" rel. to "dif" */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0; erg->top = top; erg->termVar = bool_vec_new(top->node.ne); erg->edgeRelevant = bool_vec_new(top->NE); erg->eDdif = double_vec_new(top->NE); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->termVar^[i] = FALSE; } for (j = 0; j < top->NE; j++){ erg->edgeRelevant^[j] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which @{edge->?}s are relevant to spring energy. A @{edge->?} is relevant iff it has at least one endpoint node that is variable. */ ??? NV = erg->top->node.ne; ??? NE = erg->top->NE; ??? termVar = erg->termVar^; ??? @{edge->?} = erg->top->edge^; ??? @{edge->?}Relevant = erg->edgeRelevant^; { assert((variable.ne) == NV); for (v = 0; v < NV; v++) { termVar[v] = variable[v]; } /* Find the relevant @{edge->?}s : */ for (k = 0; k < NE; k++){ @{edge->?}Relevant[k] = FALSE; } for (k = 0; k < NE; k++) { ??? e = @{edge->?}[k]; ??? u = NARROW(OrgV(e.pa), Triangulation.Node); ??? v = NARROW(OrgV(Clock(e.pa)), Triangulation.Node); ??? vvar = (termVar[u->num]) || (termVar[v->num]); { if (vvar) { @{edge->?}Relevant[k] = TRUE; } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NE = erg->top->NE; ??? @{edge->?} = erg->top->edge^; ??? @{edge->?}Relevant = erg->edgeRelevant^; ??? K = erg->K; ??? L = ((double)erg->length); ??? eDdif = erg->eDdif^; ??? termVar = erg->termVar; { void AccumTerm(*cu,cv: r4_t; VAR eDdif : double) /* Adds to "e" the energy term corresponding to a nodes "cv" and "cu". Returns also the gradient "eDdif". */ CONST Epsilon == 1.0d-10; { ??? n = r4_Sub(cu,cv); ??? dif = r4_Norm(n); ??? d2 = dif * dif + Epsilon; ??? l2 = L * L + Epsilon; ??? d3 = d2 * dif + Epsilon; { e = e + K * ((d2/l2) + (l2/d2) - 2.0); if (grad) { eDdif = 2.0 * K * ((dif/l2)-(l2/d3)); } else { eDdif = 0.0; } } } AccumTerm; void Distribute_eDdif(*u,v: uint; *eDdif: double) /* Distribute eDdif on endpoints "c[u]" and "c[v]" */ CONST Epsilon == 1.0d-10; { ??? cu = c[u]; ??? cv = c[v]; ??? n = r4_Sub(cu,cv); ??? dif = r4_Norm(n)+Epsilon; ??? eDv = eDc[v]; ??? eDu = eDc[u]; { ??? difDcu = r4_Scale(1.0/dif, n); ??? difDcv = r4_Scale(-1.0/dif,n); ??? eDcu = r4_Scale(eDdif, difDcu); ??? eDcv = r4_Scale(eDdif, difDcv); { if (termVar[v]) { eDv = r4_Add(eDv, eDcv); } if (termVar[u]) { eDu = r4_Add(eDu, eDcu); } } } } Distribute_eDdif; { for (i = 0; i < NV; i++){ eDc[i]=(r4_t){0.0, 0.0, 0.0, 0.0}; } e = 0.0; for (k = 0; k < NE; k++) { ??? e = @{edge->?}[k]; Node_t un = OrgV(e.pa)->num; Node_t vn = OrgV(Clock(e.pa))->num; { if (@{edge->?}Relevant[k]) { AccumTerm(c[un], c[vn], eDdif[k]); if (grad) { Distribute_eDdif(un, vn, eDdif[k]); } } } } } } } /* END Eval */ char * SELF_Name(SELF_T *erg)== { return "SimpleSpring(iLen = " & Fmt.Real(erg->length,Fmt.Style.Fix,prec = 3) \ ")" } /* END Name */ { } SimpleSpring. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/SpreadEnergy.c /* See {SpreadEnergy.h} */ // #INCLUDE #include // #INCLUDE // #INCLUDE REVEAL T == Public BRANDED OBJECT ElemTableRec_t *top; /* The map elements. */ double K; /* Energy normalization constant */ /* Defined by "defVar: */ termVar: REF ARRAY OF bool_t; /* Tells which terms are variable */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->top = top; erg->K = 1.0/((double)top->node.ne); erg->termVar = NEW(REF ARRAY OF bool_t, top->node.ne); /* In case the client forgets to call "defVar": */ for (i = 0 TO LAST(erg->termVar^)){ erg->termVar^[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, *variable: ARRAY OF bool_t) { /* There is a term for each existing node. The term of "v" is variable (termVar[v] == TRUE) if "v" is variable (variable[v] == TRUE). A node contributes to the energy only if "termVar[v] == TRUE", i.e. if "v" exists and "v" is variable. */ int NV = erg->top->node.ne; ??? node = erg->top->node^; ??? termVar = erg->termVar^; { assert((variable.ne) == NV); for (v = 0; v < NV; v++) { termVar[v] = variable[v]) && (node[v]->exists } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? termVar = erg->termVar^; ??? K = erg->K; { void AccumTerm(*cv: r4_t; VAR evDcv: r4_t) /* Adds to "e" the energy term corresponding to a node at "cv". Returns also the gradient "evDcv" of that term relative to "cv". */ { e = e + K * r4_NormSqr(cv); if (grad) { evDcv = r4_Scale(2.0 * K, cv) } else { evDcv = (r4_t){0.0, 0.0, 0.0, 0.0}; } } AccumTerm; { e = 0.0; for (v = 0; v < NV; v++) { if (termVar[v]) { AccumTerm(c[v], eDc[v]); } else { eDc[v] = (r4_t){0.0, 0.0, 0.0, 0.0}; } } } } } /* END Eval */ PROCEDURE Name(<*UNUSED); erg: T): char *== { return "Spread()"; } /* END Name */ { } SpreadEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/UneqVolEnergy.c /* See {UneqVolEnergy.h} */ // #INCLUDE #include // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE CONST Zero == 0.0; TYPE bool_vec_t == ARRAY OF bool_t; double_vec_t == double_vec_t; REVEAL T == Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ bool_vec_t vVar; /* TRUE if node is variable */ bool_vec_t wallRelevant; /* TRUE if wall is relevant */ vr: REF double_vec_t; /* (Work) Volume ratio of two cells incident to wall relevant */ eDvr: REF double_vec_t; /* (Work) Derivate of energy rel. to volume ratio */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0/((double)top->wall.ne); erg->top = top; erg->vVar = bool_vec_new(top->node.ne); erg->wallRelevant = bool_vec_new(top->wall.ne); /* Allocate volume ratio tables: */ erg->vr = double_vec_new(top->wall.ne); erg->eDvr = double_vec_new(top->wall.ne); /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->vVar^[i] = FALSE; } for (i = 0; i < top->wall.ne; i++){ erg->wallRelevant^[i] = FALSE; } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) VAR p1,p2: Cell; { /* Decide which wall are relevant to unequal volume energy. A wall is relevant iff it exists, has exactly two cell incident to it being least one existing cell and the wall have at least one variable corner. */ int NV = erg->top->node.ne; int NF = erg->top->wall.ne; bool_vec_t vVar = erg->vVar^; ??? wall = erg->top->wall^; ??? wallRelevant = erg->wallRelevant^; { assert((variable.ne) == NV); vVar = variable; /* Find the relevant walls: */ for (i = 0; i < NF; i++){ wallRelevant.e[i] = FALSE; } for (i = 0; i < NF; i++) { ??? f = wall[i]; ??? a = f.pa^; { p1 = PnegP(a); p2 = PposP(a); if ((p1!=NULL) && (p2!=NULL)) { ??? pvar = p1->exists) || (p2->exists; Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); Node_t w = OrgV(PrevE(a)); ??? vvar = vVar.e[u->num]) || (vVar.e[v->num]) || (vVar.e[w->num]; { if ((f->exists) && (pvar) && (vvar)) { assert(u->exists) && (v->exists) && (w->exists); wallRelevant.e[i] = TRUE; } } } } } } } /* END DefVar */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { ??? K = erg->K; int NV = erg->top->node.ne; int NF = erg->top->wall.ne; ??? wall = erg->top->wall^; bool_vec_t vVar = erg->vVar^; ??? wallRelevant = erg->wallRelevant^; ??? vr = erg->vr^; ??? eDvr = erg->eDvr^; { void Accum_vr(*u, v, w, x, y: r4_t; VAR vro: double) /* Compute the volume ratio of tetrahedrons "u w v x" (Ppos) and "u w y v" (Pneg). "n1" is the cross product "(w - u)X(v - u)X(x - u)" and "n2" is the cross product (w - u)X(y - u)X(v - u)". The coordinates "u v w" defined the common wall of two tetrahedrons where "x" is the node extremus of cell Ppos and "y" is the node extremus of cell Pneg. Note that the rigth-hand rule is valid in R^{4} for determining in which of the two possible direc- tions "a x b x c" points. */ { ??? uv = r4_Sub(v, u); ??? uw = r4_Sub(w, u); ??? ux = r4_Sub(x, u); ??? uy = r4_Sub(y, u); ??? n1 = r4_cross(uw, uv, ux); ??? n2 = r4_cross(uw, uy, uv); ??? v1 = 1.0/6.0 * r4_Norm(n1); ??? v2 = 1.0/6.0 * r4_Norm(n2); { vro = vro + v1/v2; } } Accum_vr; void Accum_e_from_vr(vr: double; double e; VAR VAR etDvr: double) /* Adds to "e" the energy term corresponding to a wall with volume ratio "vr" of cells incidents to it. Also, if "grad" is true, stores in "etDvr" the derivative of that term. */ { assert(vr!=0.0); if (vr <= 0.0) { etDvr = 0.0 } else { ??? d = vr - 1.0; ??? d2 = d * d; { e = e + K * d2; if (grad) { etDvr = 2.0 * K * d; } else { etDvr = 0.0; } } } } Accum_e_from_vr; void Distribute_eDvr(iu, iv, iw, ix, iy: uint; eDvr: double) /* Accumulates in "eDc" the gradient of "e" relative to the corners of the two tetrahedrons "iu iv iw ix", and "iu iv iw iy" given the derivative "eDv" of "e" relative to volume ratio of tetrahedrons "vr". */ void CalcPartialDerivatives( uint *u,v,w,x; double sum2; VAR VAR voDu,voDv,voDw,voDx: r4_t; ) double *term; { ??? u = c[u], v = c[v], w = c[w], x = c[x]; ??? u1 = u[0], u2 = u[1], u3 = u[2], u4 = u[3]; ??? v1 = v[0], v2 = v[1], v3 = v[2], v4 = v[3]; ??? w1 = w[0], w2 = w[1], w3 = w[2], w4 = w[3]; ??? x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3]; double d1 = u1 * (v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-w3*x2) -u2 * (v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-w3*x1) +u3 * (v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2) -(v1*(w2*x3-x2*w3)-v2*(w1*x3-x1*w3)+v3*(w1*x2-x1*w2)); double d2 = u1 * (v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4) -u2 * (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4) +u4 * (v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2) -(v1*(w2*x4-x2*w4)-v2*(w1*x4-x1*w4)+v4*(w1*x2-x1*w2)); double d3 = u2 * (v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4) -u3 * (v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4) +u4 * (v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-x2*w3) -(v2*(w3*x4-x3*w4)-v3*(w2*x4-x2*w4)+v4*(w2*x3-x2*w3)); double d4 = u1 * (v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4) -u3 * (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4) +u4 * (v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-x1*w3) -(v1*(w3*x4-x3*w4)-v3*(w1*x4-x1*w4)+v4*(w1*x3-x1*w3)); double d = (r4_t){d1,d2,d3,d4}; double d1Du1 = v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-w3*x2; double d2Du1 = v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4; double d3Du1 = Zero; double d4Du1 = v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4; double dDu1 = (r4_t){d1Du1, d2Du1, d3Du1, d4Du1}; double d1Du2 = - (v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-w3*x1); double d2Du2 = - (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4); double d3Du2 = v3 * (w4-x4) - v4 * (w3-x3) + w3*x4-x3*w4; double d4Du2 = Zero; double dDu2 = (r4_t){d1Du2, d2Du2, d3Du2, d4Du2}; double d1Du3 = v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2; double d2Du3 = Zero; double d3Du3 = - (v2 * (w4-x4) - v4 * (w2-x2) + w2*x4-x2*w4); double d4Du3 = - (v1 * (w4-x4) - v4 * (w1-x1) + w1*x4-x1*w4); double dDu3 = (r4_t){d1Du3, d2Du3, d3Du3, d4Du3}; double d1Du4 = Zero; double d2Du4 = v1 * (w2-x2) - v2 * (w1-x1) + w1*x2-x1*w2; double d3Du4 = v2 * (w3-x3) - v3 * (w2-x2) + w2*x3-x2*w3; double d4Du4 = v1 * (w3-x3) - v3 * (w1-x1) + w1*x3-x1*w3; double dDu4 = (r4_t){d1Du4, d2Du4, d3Du4, d4Du4}; double d1Dv1 = u2 * (x3-w3) + u3 * (w2-x2) - w2*x3+w3*x2; double d2Dv1 = u2 * (x4-w4) + u4 * (w2-x2) - w2*x4+x2*w4; double d3Dv1 = Zero; double d4Dv1 = u3 * (x4-w4) + u4 * (w3-x3) - w3*x4+x3*w4; double dDv1 = (r4_t){d1Dv1, d2Dv1, d3Dv1, d4Dv1}; double d1Dv2 = u1 * (w3-x3) + u3 * (x1-w1) + w1*x3-w3*x1; double d2Dv2 = u1 * (w4-x4) + u4 * (x1-w1) + w1*x4-x1*w4; double d3Dv2 = u3 * (x4-w4) + u4 * (w3-x3) - w3*x4+x3*w4; double d4Dv2 = Zero; double dDv2 = (r4_t){d1Dv2, d2Dv2, d3Dv2, d4Dv2}; double d1Dv3 = u1 * (x2-w2) + u2 * (w1-x1) - w1*x2+x1*w2; double d2Dv3 = Zero; double d3Dv3 = u2 * (w4-x4) + u4 * (x2-w2) + w2*x4-x2*w4; double d4Dv3 = u1 * (w4-x4) + u4 * (x1-w1) + w1*x4-x1*w4; double dDv3 = (r4_t){d1Dv3, d2Dv3, d3Dv3, d4Dv3}; double d1Dv4 = Zero; double d2Dv4 = u1 * (x2-w2) + u2 * (w1-x1) - w1*x2+x1*w2; double d3Dv4 = u2 * (x3-w3) + u3 * (w2-x2) - w2*x3+x2*w3; double d4Dv4 = u1 * (x3-w3) + u3 * (w1-x1) - w1*x3+x1*w3; double dDv4 = (r4_t){d1Dv4, d2Dv4, d3Dv4, d4Dv4}; double d1Dw1 = u2 * (v3-x3) + u3 * (x2-v2) + v2*x3-v3*x2; double d2Dw1 = u2 * (v4-x4) + u4 * (x2-v2) + v2*x4-x2*v4; double d3Dw1 = Zero; double d4Dw1 = u3 * (v4-x4) + u4 * (x3-v3) + v3*x4-x3*v4; double dDw1 = (r4_t){d1Dw1, d2Dw1, d3Dw1, d4Dw1}; double d1Dw2 = u1 * (x3-v3) + u3 * (v1-x1) - v1*x3+v3*x1; double d2Dw2 = u1 * (x4-v4) + u4 * (v1-x1) - v1*x4+x1*v4; double d3Dw2 = u3 * (v4-x4) + u4 * (x3-v3) + v3*x4-x3*v4; double d4Dw2 = Zero; double dDw2 = (r4_t){d1Dw2, d2Dw2, d3Dw2, d4Dw2}; double d1Dw3 = u1 * (v2-x2) + u2 * (x1-v1) + v1*x2-x1*v2; double d2Dw3 = Zero; double d3Dw3 = u2 * (x4-v4) + u4 * (v2-x2) - v2*x4+x2*v4; double d4Dw3 = u1 * (x4-v4) + u4 * (v1-x1) - v1*x4+x1*v4; double dDw3 = (r4_t){d1Dw3, d2Dw3, d3Dw3, d4Dw3}; double d1Dw4 = Zero; double d2Dw4 = u1 * (v2-x2) + u2 * (x1-v1) + v1*x2-x1*v2; double d3Dw4 = u2 * (v3-x3) + u3 * (x2-v2) + v2*x3-x2*v3; double d4Dw4 = u1 * (v3-x3) + u3 * (x1-v1) + v1*x3-x1*v3; double dDw4 = (r4_t){d1Dw4, d2Dw4, d3Dw4, d4Dw4}; double d1Dx1 = u2 * (w3-v3) + u3 * (v2-w2) - v2*w3+v3*w2; double d2Dx1 = u2 * (w4-v4) + u4 * (v2-w2) - v2*w4+w2*v4; double d3Dx1 = Zero; double d4Dx1 = u3 * (w4-v4) + u4 * (v3-w3) - v3*w4+w3*v4; double dDx1 = (r4_t){d1Dx1, d2Dx1, d3Dx1, d4Dx1}; double d1Dx2 = u1 * (v3-w3) + u3 * (w1-v1) + v1*w3-v3*w1; double d2Dx2 = u1 * (v4-w4) + u4 * (w1-v1) + v1*w4-w1*v4; double d3Dx2 = u3 * (w4-v4) + u4 * (v3-w3) + v4*w3-v3*w4; double d4Dx2 = Zero; double dDx2 = (r4_t){d1Dx2, d2Dx2, d3Dx2, d4Dx2}; double d1Dx3 = u1 * (w2-v2) + u2 * (v1-w1) - v1*w2+w1*v2; double d2Dx3 = Zero; double d3Dx3 = u2 * (v4-w4) + u4 * (w2-v2) + v2*w4-w2*v4; double d4Dx3 = u1 * (v4-w4) + u4 * (w1-v1) + v1*w4-w1*v4; double dDx3 = (r4_t){d1Dx3, d2Dx3, d3Dx3, d4Dx3}; double d1Dx4 = Zero; double d2Dx4 = u1 * (w2-v2) + u2 * (v1-w1) - v1*w2+w1*v2; double d3Dx4 = u2 * (w3-v3) + u3 * (v2-w2) - v2*w3+w2*v3; double d4Dx4 = u1 * (w3-v3) + u3 * (v1-w1) - v1*w3+w1*v3; double dDx4 = (r4_t){d1Dx4, d2Dx4, d3Dx4, d4Dx4}; { sum2 = d1*d1 + d2*d2 + d3*d3 + d4*d4; term = 1.0/sqrt(sum2); voDu[0] = term * r4_dot(d,dDu1); voDu[1] = term * r4_dot(d,dDu2); voDu[2] = term * r4_dot(d,dDu3); voDu[3] = term * r4_dot(d,dDu4); voDv[0] = term * r4_dot(d,dDv1); voDv[1] = term * r4_dot(d,dDv2); voDv[2] = term * r4_dot(d,dDv3); voDv[3] = term * r4_dot(d,dDv4); voDw[0] = term * r4_dot(d,dDw1); voDw[1] = term * r4_dot(d,dDw2); voDw[2] = term * r4_dot(d,dDw3); voDw[3] = term * r4_dot(d,dDw4); voDx[0] = term * r4_dot(d,dDx1); voDx[1] = term * r4_dot(d,dDx2); voDx[2] = term * r4_dot(d,dDx3); voDx[3] = term * r4_dot(d,dDx4); voDu = (r4_t){voDu[0], voDu[1], voDu[2], voDu[3]}; voDv = (r4_t){voDv[0], voDv[1], voDv[2], voDv[3]}; voDw = (r4_t){voDw[0], voDw[1], voDw[2], voDw[3]}; voDx = (r4_t){voDx[0], voDx[1], voDx[2], voDx[3]}; } } CalcPartialDerivatives; VAR vpDu,vpDv,vpDw,vpDx,vnDu,vnDv,vnDw,vnDy : r4_t; sum1, sum2 : double; { CalcPartialDerivatives(iu,iv,iw,ix,sum1,vpDu,vpDv,vpDw,vpDx); CalcPartialDerivatives(iu,iv,iw,iy,sum2,vnDu,vnDv,vnDw,vnDy); ??? vrDu1 = (sqrt(sum2) * vpDu[0] - sqrt(sum1) * vnDu[0])/sum2; ??? vrDu2 = (sqrt(sum2) * vpDu[1] - sqrt(sum1) * vnDu[1])/sum2; ??? vrDu3 = (sqrt(sum2) * vpDu[2] - sqrt(sum1) * vnDu[2])/sum2; ??? vrDu4 = (sqrt(sum2) * vpDu[3] - sqrt(sum1) * vnDu[3])/sum2; double vrDv1 = (sqrt(sum2) * vpDv[0] - sqrt(sum1) * vnDv[0])/sum2; double vrDv2 = (sqrt(sum2) * vpDv[1] - sqrt(sum1) * vnDv[1])/sum2; double vrDv3 = (sqrt(sum2) * vpDv[2] - sqrt(sum1) * vnDv[2])/sum2; double vrDv4 = (sqrt(sum2) * vpDv[3] - sqrt(sum1) * vnDv[3])/sum2; double vrDw1 = (sqrt(sum2) * vpDw[0] - sqrt(sum1) * vnDw[0])/sum2; double vrDw2 = (sqrt(sum2) * vpDw[1] - sqrt(sum1) * vnDw[1])/sum2; double vrDw3 = (sqrt(sum2) * vpDw[2] - sqrt(sum1) * vnDw[2])/sum2; double vrDw4 = (sqrt(sum2) * vpDw[3] - sqrt(sum1) * vnDw[3])/sum2; double vrDx1 = (sqrt(sum2) * vpDx[0])/sum2; double vrDx2 = (sqrt(sum2) * vpDx[1])/sum2; double vrDx3 = (sqrt(sum2) * vpDx[2])/sum2; double vrDx4 = (sqrt(sum2) * vpDx[3])/sum2; double vrDy1 = -(sqrt(sum1) * vnDy[0])/sum2; double vrDy2 = -(sqrt(sum1) * vnDy[1])/sum2; double vrDy3 = -(sqrt(sum1) * vnDy[2])/sum2; double vrDy4 = -(sqrt(sum1) * vnDy[3])/sum2; double eDu1 = eDvr * vrDu1; double eDu2 = eDvr * vrDu2; double eDu3 = eDvr * vrDu3; double eDu4 = eDvr * vrDu4; double eDv1 = eDvr * vrDv1; double eDv2 = eDvr * vrDv2; double eDv3 = eDvr * vrDv3; double eDv4 = eDvr * vrDv4; double eDw1 = eDvr * vrDw1; double eDw2 = eDvr * vrDw2; double eDw3 = eDvr * vrDw3; double eDw4 = eDvr * vrDw4; double eDx1 = eDvr * vrDx1; double eDx2 = eDvr * vrDx2; double eDx3 = eDvr * vrDx3; double eDx4 = eDvr * vrDx4; double eDy1 = eDvr * vrDy1; double eDy2 = eDvr * vrDy2; double eDy3 = eDvr * vrDy3; double eDy4 = eDvr * vrDy4 { if (vVar.e[iu]) { eDc[iu,0] = eDc[iu,0] + eDu1; eDc[iu,1] = eDc[iu,1] + eDu2; eDc[iu,2] = eDc[iu,2] + eDu3; eDc[iu,3] = eDc[iu,3] + eDu4; } if (vVar.e[iv]) { eDc[iv,0] = eDc[iv,0] + eDv1; eDc[iv,1] = eDc[iv,1] + eDv2; eDc[iv,2] = eDc[iv,2] + eDv3; eDc[iv,3] = eDc[iv,3] + eDv4; } if (vVar.e[iw]) { eDc[iw,0] = eDc[iw,0] + eDw1; eDc[iw,1] = eDc[iw,1] + eDw2; eDc[iw,2] = eDc[iw,2] + eDw3; eDc[iw,3] = eDc[iw,3] + eDw4; } if (vVar.e[ix]) { eDc[ix,0] = eDc[ix,0] + eDx1; eDc[ix,1] = eDc[ix,1] + eDx2; eDc[ix,2] = eDc[ix,2] + eDx3; eDc[ix,3] = eDc[ix,3] + eDx4; } if (vVar.e[iy]) { eDc[iy,0] = eDc[iy,0] + eDy1; eDc[iy,1] = eDc[iy,1] + eDy2; eDc[iy,2] = eDc[iy,2] + eDy3; eDc[iy,3] = eDc[iy,3] + eDy4; } } } Distribute_eDvr; { /* Clear volume ratio accumulators: */ for (j = 0; j < NF; j++){ vr[j] = 0.0; } /* Enumerate walls and accumulate volume ratio of cells incidents. */ for (j = 0; j < NF; j++) { if (wallRelevant.e[j]) { ??? f = wall[j]; ??? a = f.pa^; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(NextF(a)))->num; Node_t yn = OrgV(PrevE(PrevF(a)))->num; { Accum_vr(c[un], c[vn], c[wn], c[xn], c[yn], vr[j]) } } } /* Compute energy "e" from volumes ratios, and the gradient "eDvr": */ e = 0.0; for (j = 0; j < NF; j++) { if (wallRelevant.e[j]) { Accum_e_from_vr(vr[j], e, eDvr[j]) } else { eDvr[j] = 0.0 } } /* Now distribute "eDvr" over "eDc": */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, ..}; } if (grad) { for (j = 0; j < NF; j++) { if (wallRelevant.e[j]) { ??? f = wall[j]; ??? a = f.pa^; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(NextF(a)))->num; Node_t yn = OrgV(PrevE(PrevF(a)))->num; { Distribute_eDvr(un, vn, wn, xn, yn, eDvr[j]) } } } } } } } /* END Eval */ PROCEDURE Name(<*UNUSED); erg: T): char *== { return "Unequal()"; } /* END Name */ { } UneqVolEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/VarKamSpring.c /* See {VarKamSpring.h} */ // #INCLUDE #define VarKamSpring_C_author \ "Modified by L.A.P.Lozada on 2000-11-18." #include // #INCLUDE #include // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE CONST inf == 10.0E30; TYPE double bool_t = bool_t; bool_vec_t == ARRAY OF bool_t; double double = double; double_vec_t == double_vec_t; double NAT = uint; NATS == ARRAY OF NAT; double DistanceMatrix = ARRAY OF ARRAY OF REAL; REVEAL double T = Public BRANDED OBJECT ElemTableRec_t *top; /* The map elements. */ termVar: REF bool_vec_t; /* TRUE if node is variable & existing */ m : REF DistanceMatrix; /* Matrix of initial distances */ eDdif: REF double_vec_t_vec_t; /* (Work) Gradient of "e" rel. to "dif" */ double L; /* length of spring */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) double *dmax; { ??? NV = top->node.ne; { erg->m = ComputeDistanceMatrix(top); /*PrintHalfMatrix(erg->m, NV);*/ ShortestPath(erg->m, NV); /* PrintHalfMatrix(erg->m, NV); */ dmax = FLOAT(FindMaxDistance(erg->m, NV), double); erg->L = FLOAT(erg->length,double)/dmax; erg->top = top; erg->termVar = bool_vec_new(NV); erg->eDdif = double_vec_t_vec_new(NV, NV); /*PrintHalfMatrix(erg->k, NV);*/ /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->node.ne; i++){ erg->termVar^[i] = FALSE; } } } /* END DefTop */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which nodes are relevant to kamada energy. A node is relevant iff it is variable. */ int NV = erg->top->node.ne; ??? termVar = erg->termVar^; { /* Find the relevant nodes: */ assert((variable.ne) == NV); for (v = 0; v < NV; v++) { termVar[v] = variable[v]; } } } /* END DefVar */ DistanceMatrix *ComputeDistanceMatrix(ElemTableRec_t *top, )== REF DistanceMatrix m ; { m = NEW(REF ARRAY OF ARRAY OF REAL, top->node.ne, top->node.ne); for (i = 0; i < top->node.ne; i++) { for (j = 0; j < top->node.ne; j++) { m[i,j] = inf; } m[i,i] = 0.0; } ??? cdg = ComputeCorrectedDegrees(top)^; { for (i = 0; i < top->NE; i++) { ??? a = top->edge[i].pa; Place_t b = Clock(a); Node_t i = OrgV(a)->num; Node_t j = OrgV(b)->num; ??? ni = FLOAT(cdg[i] ,double); double nj = FLOAT(cdg[j], double); double lij = FLOAT(sqrt(ni/nj + nj/ni), REAL) { m[i,j] = lij; m[j,i] = lij; } } } return m; } /* END ComputeDistanceMatrix */ NATS *ComputeCorrectedDegrees(ElemTableRec_t *top)== /* Computes the corrected degree of each node, defined as the true degree for interior nodes, and the true degree plus the interior degree for border nodes. */ { ??? rd = NEW(REF NATS, top->node.ne), d == rd^; double border = bool_vec_new(top->node.ne)^; { for (i = 0 TO (d.ne-1)){ d[i] = 0; border[i] = FALSE; } /* Tally interior @{edge->?}s twice, border edegs once: */ for (i = 0; i < top->NE; i++) { ??? a = top->edge[i].pa; Place_t b = Clock(a); Node_t un = OrgV(a)->num; Node_t vn = OrgV(b)->num; { if ((EdgeIsBorder(a))) { border[un] = TRUE; border[vn] = TRUE; INC(d[un]); INC(d[vn]) } else { INC(d[un],2); INC(d[vn],2) } } } /* Correct count for non-border nodes: */ for (i = 0 TO (d.ne-1)) { if (! border[i]) { assert(d[i] % 2 == 0); d[i] = d[i] DIV 2 } } return rd; } } /* END ComputeCorrectedDegrees */ bool_t EdgeIsBorder(Place_t @p) Place_t b = a; { do { if ((Pneg(a) == NULL)){ return TRUE; } b = NextF(b); } while (b != a); return FALSE; } /* END EdgeIsBorder */ REAL FindMaxDistance( *m: REF DistanceMatrix; INTEGER n; ) max = 0.0; { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] > max) { max = m[i,j]; } } } return max; } /* END FindMaxDistance */ double CalculateStrength(dist: REAL) { if (dist == 0.0){ return 0.0; } else { ??? d = FLOAT(dist, double); { return 1.0/(d*d); } } } /* END CalculateStrength */ double CalculateLength(dist : REAL) { if (dist == 0.0){ return 0.0; } else { ??? d = FLOAT(dist, double); { return d; } } } /* END CalculateLength */ /* UNUSED */ void PrintDistanceMatrix(*m : REF DistanceMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.Real(m[i,j], prec=2, style=Fmt.Style.Fix) & " "); } } fprintf(stderr, "\n"); } } /* END PrintDistanceMatrix */ /* UNUSED */ void PrintHalfMatrix(*m : REF DistanceMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.Real(m[i,j], prec=2, style=Fmt.Style.Fix) & " "); } } fprintf(stderr, "\n"); } } /* END PrintHalfMatrix */ void ShortestPath(VAR m : REF DistanceMatrix; n : INTEGER) REAL *s; { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[j,i] < inf) { for (k = 0; k < n; k++) { if (m[i,k] < inf) { s = m[j,i] + m[i,k]; if (s < m[j,k]){ m[j,k] = s; } } } } } } } ShortestPath; void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? eDdif = erg->eDdif^; ??? termVar = erg->termVar; ??? length = erg->L; ??? strength = FLOAT(erg->strength,double); double m = erg->m^; { void AccumTerm(*u: NAT) /* Adds to "e" the energy term corresponding to a node "u". Returns also the gradient "eDdif". */ CONST Epsilon == 1.0d-10; { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? cv = c[i]; ??? n = r4_Sub(cu,cv); double dif = r4_Norm(n); double d2 = dif * dif + Epsilon; double duv = m[u,i]; double luv = length * CalculateLength(duv); double kuv = strength * CalculateStrength(duv); double l2 = luv * luv + Epsilon; double d3 = d2 * dif + Epsilon; { e = e + kuv * ( (d2/l2) + (l2/d2) - 2.0); if (grad) { eDdif[u,i] = 2.0 * kuv * ( (dif/l2) - (l2/d3)); eDdif[i,u] = eDdif[u,i]; } else { eDdif[u,i] = 0.0; eDdif[i,u] = eDdif[u,i]; } } } } } AccumTerm; void Distribute_eDdif(*u: NAT) /* Distribute eDdif on endpoints "c[u]" and "c[v]" */ CONST Epsilon == 1.0d-10; { ??? cu = c[u]; { for (i = u+1; i < NV; i++) { ??? ci = c[i]; ??? n = r4_Sub(cu, ci); ??? dif = r4_Norm(n)+Epsilon; ??? eDi = eDc[i]; ??? eDu = eDc[u]; ??? difDcu = r4_Scale(1.0/dif, n); ??? difDci = r4_Scale(-1.0/dif,n); ??? eDcu = r4_Scale(eDdif[u,i], difDcu); ??? eDci = r4_Scale(eDdif[u,i], difDci); { if (termVar[i]) { eDi = r4_Add(eDi, eDci); } if (termVar[u]) { eDu = r4_Add(eDu, eDcu); } } } } } Distribute_eDdif; { for (i = 0; i < NV; i++){ eDc[i]=(r4_t){0.0, 0.0, 0.0, 0.0}; } e = 0.0; for (l = 0; l < NV; l++) { if (termVar[l]) { AccumTerm(l); if (grad) { Distribute_eDdif(l); } } } } } } Eval; char * SELF_Name(SELF_T *erg)== { return "VarKamada(length = " & Fmt.Real(erg->length,Fmt.Style.Fix,prec = 3) \ " strength = " & Fmt.Real(erg->strength,Fmt.Style.Fix,prec= 3) & ")"; } /* END Name */ { } VarKamSpring. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/VarWindingEnergy.c /* See {VarWindingEnergy.h} */ // #INCLUDE #include #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE TYPE double bool_t = bool_t; double bool_vec_t = ARRAY OF bool_t; double NAT = uint; double NATS = uint_vec_t; REVEAL double T = Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ termOK: REF bool_vec_t; /* The terms that should be included in the energy. */ term: REF Terms; /* Nodes in each term. */ rDpw, sDpw: REF Coords3D_t; /* Work areas for "Eval". */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } TYPE double Term = RECORD /* Node numbers included in some energy term. */ NAT un, vn; /* Endpoints of some @{edge->?}. */ wn: REF NATS; /* Tips of walls incident to that @{edge->?}. */ ex: REF bool_vec_t; /* "ex[i]" == cell between wn[i] and wn[i-1] exists. */ } double Terms = ARRAY OF Term; CONST Debug == FALSE; SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0/((double)top->NE); erg->top = top; erg->termOK = bool_vec_new(top->NE); erg->term = CollectTerms(top); /* Size of "rDpw", "sDpw" is maximum @{edge->?} degree: */ ??? maxDeg = Max@{Edge->?}Degree(erg->term^); { erg->rDpw = NEW(REF Coords3D_t, maxDeg); erg->sDpw = NEW(REF Coords3D_t, maxDeg); } /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->NE; i++){ erg->termOK[i] = FALSE; } } /* END DefTop */ Terms *CollectTerms(ElemTableRec_t *top)== /* Collects relevant nodes for each @{edge->?}. */ Place_t *b; k: NAT; { ??? NE = top->NE; ??? termr = NEW(REF Terms, NE), term == termr^; { for (i = 0; i < NE; i++) { ??? e = top->edge[i]; ??? a = e.pa; ??? deg = DegreeOfWall(a); ??? wnr = NEW(REF NATS, deg), wn == wnr^; ??? exr = bool_vec_new(deg), ex == exr^; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; { b = a; k = 0; do { wn[k] = OrgV(PrevE(b))->num; ex[k] = Pneg(b)!=NULL; b = NextF(b); k++ } while (b != a); assert(k == deg); term[i] = Term{un = un, vn = vn, wn = wnr, ex = exr} } } return termr; } } /* END CollectTerms */ PROCEDURE Max@{Edge->?}Degree(*term: Terms): NAT == maxDeg: NAT = 0; { for (i = 0 TO (term.ne-1)){ maxDeg = MAX(maxDeg, ((term[i].wn^).ne)) } return maxDeg; } /* END Max@{Edge->?}Degree */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which @{edge->?}s are relevant to "VarWinding" energy. A @{edge->?} is relevant iff its star includes at least one variable node.*/ ??? termOK = erg->termOK^; ??? @{edge->?} = erg->top->edge^; { assert((variable.ne) == erg->top->node.ne); fprintf(stderr, "VarWindingEnergy: relevant @{edge->?}s == { "); for (i = 0 TO (termOK.ne-1)) { ??? e = @{edge->?}[i]; { assert(e->num == i); termOK[i] = e->exists) && (@{Edge->?}StarIsVariable(e.pa, variable); if (termOK[i]){ fprintf(stderr, " " & Fmt.Int(i)); } } } fprintf(stderr, " }\n"); } } /* END DefVar */ PROCEDURE @{Edge->?}StarIsVariable(Place_t @p, bool_vec_t *variable): bool_t == Place_t *b; { Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); { if ((variable[u->num]) || (variable[v->num])) { return TRUE; } else { b = a; do { Node_t w = OrgV(PrevE(b)); { if (variable[w->num]){ return TRUE;} } b = NextF(b) } while (b != a); return FALSE; } } } /* END @{Edge->?}StarIsVariable */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NE = erg->top->NE; ??? termOK = erg->termOK^; ??? term = erg->term^; ??? K = erg->K; ??? rDpw = erg->rDpw^; ??? sDpw = erg->sDpw^; { e = 0.0; /* Clear gradient accumulators */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, ..}; } /* Enumerate @{edge->?}s and compute @{edge->?} sums: */ for (i = 0; i < NE; i++) { if (termOK[i]) { AddTerm(term[i], c, K, grad, e, eDc, rDpw, sDpw) } } } } /* END Eval */ void AddTerm( Term *term; Coords_t *c; double K; bool_t grad; VAR /*IO*/ e: double; VAR /*IO*/ eDc: Gradient; VAR rDpw, sDpw: Coords3D_t; /* Work areas. */ ) /* Adds one term of the energy to "e". If "grad" is set, also adds the gradient of that term to "eDc". */ double r, s; /* Radial and perimetral sums for term. */ rDpu, rDpv: r3_t; /* Derivatives of "r" wrt @{edge->?} endpoints. */ sDpu, sDpv: r3_t; /* Derivatives of "s" wrt @{edge->?} endpoints. */ double t; /* An energy term, corresponding to a single @{edge->?}. */ double tDr, tDs; /* Derivatives of "t" w.r.t. "r" and "s". */ NAT gaps; /* Degree of "e", and num of missing cells. */ double SNorm, RNorm; /* Normalization factors for "r" and "s". */ CONST double Epsilon = 1.0d-20; /* To avoid divide by zero. */ double Pi = M_PI; /* Pi */ double HfPi = 1.5707963267948966; /* Pi/2 */ { ??? un = term.un; ??? pu == SUBARRAY(c[un], 0, 3), ??? vn = term.vn, pv == SUBARRAY(c[vn], 0, 3); ??? h = r3_sub(pv, pu); ??? h2 = LR3.Dot(h, h); double hm = sqrt(h2); ??? wn = term.wn^; ??? ex = term.ex^; double N = FLOAT((wn.ne), double); { void Compute_r_s_Perimeter() /* Returns in "r" and "s" the sums corresponding to the given term of the energy ("Perimeter" formula). Also, if "grad" is set, computes the gradients "rDpu", "rDPv", "rDpw[k]" of "r" relative to the 3D coordinates of relevant nodes, and similarly for "s". Also defines the geometry-independent constants "RNorm" and "SNorm", such that a regular @{edge->?} star of height "h" and radius "r" has "r == RNorm·h^2·b^2" and "s == SNorm·h^2·b^2". */ uint *kx, xn; px: r3_t; gaps: NAT; { r = Epsilon; s = Epsilon; gaps = 0; if (grad) { rDpu = (r3_t){0.0,..}; rDpv = (r3_t){0.0,..}; sDpu = (r3_t){0.0,..}; sDpv = (r3_t){0.0,..}; for (i = 0 TO (wn.ne-1)) { rDpw[i] = (r3_t){0.0,..}; sDpw[i] = (r3_t){0.0,..} } } kx = (wn.ne-1); xn = wn[kx]; px = SUBARRAY(c[xn], 0, 3); for (ky = 0 TO (wn.ne-1)) { ??? yn = wn[ky]; ??? py = SUBARRAY(c[yn], 0, 3); double fy = r3_sub(py, pu); double ry = LR3Extras.Cross(h, fy); double rb = LR3.Dot(ry,ry); double gy = r3_sub(py, px); double sy = LR3Extras.Cross(h, gy); double sb = LR3.Dot(sy,sy) { r = r + rb; if (ex[ky]){ s = s + sb }else{ gaps++; } if (grad) { ??? rbDry = r3_scale(2.0, ry); double rbDfy = LR3Extras.Cross(rbDry, h); double rbDh = LR3Extras.Cross(fy, rbDry) { if (Debug) { PrL("rb == ", rb); PrEOL(); PrV("rbDfy == ", rbDfy); PrEOL(); PrV("rbDh == ", rbDh); PrEOL(); } rDpw[ky] = r3_add(rDpw[ky], rbDfy); rDpu = r3_sub(rDpu, r3_add(rbDfy, rbDh)); rDpv = r3_add(rDpv, rbDh); if (ex[ky]) { ??? sbDsy = r3_scale(2.0, sy); double sbDgy = LR3Extras.Cross(sbDsy, h); double sbDh = LR3Extras.Cross(gy, sbDsy); { if (Debug) { PrL("sb == ", sb); PrEOL(); PrV("sbDgy == ", sbDgy); PrEOL(); PrV("sbDh == ", sbDh); PrEOL(); } sDpw[ky] = r3_add(sDpw[ky], sbDgy); sDpw[kx] = r3_sub(sDpw[kx], sbDgy); sDpu = r3_sub(sDpu, sbDh); sDpv = r3_add(sDpv, sbDh); } } } } kx = ky; xn = yn; px = py; } } if (Debug) { PrL("r == ", r); PrEOL(); PrV("rDpu == ", rDpu); PrEOL(); PrV("rDpv == ", rDpv); PrEOL(); PrL("s == ", s); PrEOL(); PrV("sDpu == ", sDpu); PrEOL(); PrV("sDpv == ", sDpv); PrEOL(); PrEOL(); } RNorm = N; if (gaps == 0) { /* @{Edge->?} is interior; ideally, winding number should be ±1 */ ??? sn = Math.sin(Pi/N); { SNorm = 4.0*N*sn*sn } } else { assert(gaps < (wn.ne)); /* @{Edge->?} is on border; winding number should be ±1/2, with fencepost correction */ ??? G = ((double)gaps); ??? sn = Math.sin(HfPi/(N-G)); { SNorm = 4.0*(N-G)*sn*sn } } } Compute_r_s_Perimeter; void Compute_r_s_Area() /* Returns in "r" and "s" the sums corresponding to the given term of the energy ("Area" formula). Also, if "grad" is set, computes the gradients "rDpu", "rDPv", "rDpw[k]" of "r" relative to the 3D coordinates of relevant nodes, and similarly for "s". Also defines the geometry-independent constants "RNorm" and "SNorm", such that a regular @{edge->?} star of height "h" and radius "r" has "r == RNorm·h^2·b^2" and "s == SNorm·h^2·b^2". */ uint *kx, xn; px: r3_t; gaps: NAT; { r = Epsilon; s = Epsilon; gaps = 0; if (grad) { rDpu = (r3_t){0.0,..}; rDpv = (r3_t){0.0,..}; sDpu = (r3_t){0.0,..}; sDpv = (r3_t){0.0,..}; for (i = 0 TO (wn.ne-1)) { rDpw[i] = (r3_t){0.0,..}; sDpw[i] = (r3_t){0.0,..} } } kx = (wn.ne-1); xn = wn[kx]; px = SUBARRAY(c[xn], 0, 3); for (ky = 0 TO (wn.ne-1)) { ??? yn = wn[ky]; ??? py = SUBARRAY(c[yn], 0, 3); double fy = r3_sub(py, pu); double ry = LR3Extras.Cross(h, fy); double rb = LR3.Dot(ry,ry); double dy = LR3Extras.Cross(fx,fy); double sb = LR3.Dot(h, dy); { r = r + rb; if (ex[ky]){ s = s + sb }else{ gaps++; } if (grad) { ??? rbDry = r3_scale(2.0, ry); double rbDfy = LR3Extras.Cross(rbDry, h); double rbDh = LR3Extras.Cross(fy, rbDry); { if (Debug){ PrL("rb == ", rb); PrEOL(); PrV("rbDfy == ", rbDfy); PrEOL(); PrV("rbDh == ", rbDh); PrEOL(); } rDpw[ky] = r3_add(rDpw[ky], rbDfy); rDpu = r3_sub(rDpu, r3_add(rbDfy, rbDh)); rDpv = r3_add(rDpv, rbDh); if (ex[ky]) { ??? sbDdy = fx; ??? sbDry = LR3Extras.Cross(h, sbDdy); double sbDfy = - sbDry * h ×; double sbDfx =; double sbDgy = LR3Extras.Cross(sbDsy, h); double sbDh = LR3Extras.Cross(gy, sbDsy) { if (Debug) { PrL("sb == ", sb); PrEOL(); PrV("sbDgy == ", sbDgy); PrEOL(); PrV("sbDh == ", sbDh); PrEOL(); } sDpw[ky] = r3_add(sDpw[ky], sbDgy); sDpw[kx] = r3_sub(sDpw[kx], sbDgy); sDpu = r3_sub(sDpu, sbDh); sDpv = r3_add(sDpv, sbDh); } } } } kx = ky; xn = yn; px = py; } } if (Debug) { PrL("r == ", r); PrEOL(); PrV("rDpu == ", rDpu); PrEOL(); PrV("rDpv == ", rDpv); PrEOL(); PrL("s == ", s); PrEOL(); PrV("sDpu == ", sDpu); PrEOL(); PrV("sDpv == ", sDpv); PrEOL(); PrEOL(); } } Compute_r_s_Area; void Compute_RNorm_SNorm_Perimeter() /* Defines "RNorm,SNorm" which are the expected values of "r,s", for a regular @{edge->?} star, divided by "h^2·b^2" where "h" is the length of the @{edge->?} and "b" is the radius of the star. */ { RNorm = N; if (gaps == 0) { /* @{Edge->?} is interior; ideally, winding number should be ±1 */ ??? sn = Math.sin(Pi/N); { SNorm = 4.0*N*sn*sn } } else { assert(gaps < (wn.ne)); /* @{Edge->?} is on border; winding number should be ±1/2, with fencepost correction */ ??? G = ((double)gaps); ??? sn = Math.sin(HfPi/(N-G)); { SNorm = 4.0*(N-G)*sn*sn } } } Compute_RNorm_SNorm; void Compute_t_from_r_s() /* Returns in "t" the energy term corresponding to an @{edge->?} with sums "r" and "s" Also, if "grad" is true, stores in "tDr" and "tDs" the derivatives of the term relative to those sums. */ { ??? R = r/RNorm; ??? S = s/SNorm; ??? f = R/S; ??? g = S/R; ??? y = f + g; ??? z = y*y; { t = K * (z - 4.0); if (Debug) { PrL("R == ", R); PrL("S == ", S); PrL("t == ", t); PrEOL(); } if (grad) { ??? zDy = 2.0 * y; ??? zDr = zDy*(1.0/S - g/R)/RNorm; double zDs = zDy*(1.0/R - f/S)/SNorm; { tDr = K * zDr; tDs = K * zDs } } else { tDr = 0.0; tDs = 0.0; } } } Compute_t_from_r_s; void Distribute_tDr_tDs() /* Accumulates in "eDc" the gradient of an energy term "t" relative to the nodes in the star of the corresponding @{edge->?} "Edg(a)", given the derivatives "tDr" and "tDs" of the term relative to the edge sums "r" and "s". */ void AddGradientToNode(vn: NAT; rDpv, sDpv: r3_t) /* Adds to "eDc" the contribution due to node "vn". */ { ??? eDcv = eDc[vn]; { eDcv[0] = eDcv[0] + tDr * rDpv[0] + tDs * sDpv[0]; eDcv[1] = eDcv[1] + tDr * rDpv[1] + tDs * sDpv[1]; eDcv[2] = eDcv[2] + tDr * rDpv[2] + tDs * sDpv[2] } } AddGradientToNode; { AddGradientToNode(un, rDpu, sDpu); AddGradientToNode(vn, rDpv, sDpv); for (k = 0 TO (wn.ne-1)) { AddGradientToNode(wn[k], rDpw[k], sDpw[k]) } } Distribute_tDr_tDs; { Compute_r_s(); Compute_t_from_r_s(); e = e + t; if (grad){ Distribute_tDr_tDs();} } } } /* END AddTerm */ PROCEDURE Name(<*UNUSED);erg: T) : char *== { return "VarWinding()"; } /* END Name */ void PrI(prefix: char *; x: INTEGER) { fprintf(stderr, " "); fprintf(stderr, prefix); fprintf(stderr, Fmt.Pad(Fmt.Int(x), 12)); } /* END PrI */ void PrL(prefix: char *; x: double) { fprintf(stderr, " "); fprintf(stderr, prefix); fprintf(stderr, Fmt.Pad(Fmt.LongReal(x, style = Fmt.Style.Fix, prec = 8), 22) ); } /* END PrL */ void PrV(prefix: char *; x: r3_t) { fprintf(stderr, " "); fprintf(stderr, prefix); for (i = 0; i < 3; i++) { fprintf(stderr, Fmt.Pad(Fmt.LongReal(x[i], style = Fmt.Style.Fix, prec = 8), 21) & " " ) } } /* END PrV */ void PrEOL() { fprintf(stderr, "\n"); } /* END PrEOL */ { } VarWindingEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/WindingEnergy.c /* See {WindingEnergy.h} */ // #INCLUDE #include #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE TYPE double bool_t = bool_t; double bool_vec_t = ARRAY OF bool_t; double NAT = uint; double NATS = uint_vec_t; double Coords3D_t = r3_vec_t; REVEAL double T = Public BRANDED OBJECT double K; /* The energy normalization factor */ ElemTableRec_t *top; /* The map elements. */ termOK: REF bool_vec_t; /* The terms that should be included in the energy. */ term: REF Terms; /* Nodes in each term. */ rDpw, sDpw: REF Coords3D_t; /* Work areas for "Eval". */ OVERRIDES init = Init; defTop = DefTop; defVar = DefVar; eval = Eval; name = Name; } TYPE double Term = RECORD /* Node numbers included in some energy term. */ NAT un, vn; /* Endpoints of some @{edge->?}. */ wn: REF NATS; /* Tips of walls incident to that @{edge->?}. */ ex: REF bool_vec_t; /* "ex[i]" == cell between wn[i] and wn[i-1] exists. */ } double Terms = ARRAY OF Term; CONST Debug == FALSE; SELF_Init(SELF_T *erg) { return erg; } /* END Init */ void SELF_DefTop(SELF_T *erg, ElemTableRec_t *top) { erg->K = 1.0/((double)top->NE); erg->top = top; erg->termOK = bool_vec_new(top->NE); erg->term = CollectTerms(top); /* Size of "rDpw", "sDpw" is maximum @{edge->?} degree: */ ??? maxDeg = Max@{Edge->?}Degree(erg->term^); { erg->rDpw = NEW(REF Coords3D_t, maxDeg); erg->sDpw = NEW(REF Coords3D_t, maxDeg); } /* Just in case the client forgets to call "defVar": */ for (i = 0; i < top->NE; i++){ erg->termOK[i] = FALSE; } } /* END DefTop */ Terms *CollectTerms(ElemTableRec_t *top)== /* Collects relevant nodes for each @{edge->?}. */ Place_t *b; k: NAT; { ??? NE = top->NE; ??? termr = NEW(REF Terms, NE), term == termr^; { for (i = 0; i < NE; i++) { ??? e = top->edge[i]; ??? a = e.pa; ??? deg = DegreeOfWall(a); ??? wnr = NEW(REF NATS, deg), wn == wnr^; double exr = bool_vec_new(deg), ex == exr^; double un = OrgV(a)->num; double vn = OrgV(NextE(a))->num; { b = a; k = 0; do { wn[k] = OrgV(PrevE(b))->num; ex[k] = Pneg(b)!=NULL; b = NextF(b); k++ } while (b != a); assert(k == deg); term[i] = Term{un = un, vn = vn, wn = wnr, ex = exr} } } return termr; } } /* END CollectTerms */ PROCEDURE Max@{Edge->?}Degree(*term: Terms): NAT == maxDeg: NAT = 0; { for (i = 0 TO (term.ne-1)){ maxDeg = MAX(maxDeg, ((term[i].wn^).ne)) } return maxDeg; } /* END Max@{Edge->?}Degree */ void SELF_DefVar(SELF_T *erg, bool_vec_t *variable) { /* Decide which @{edge->?}s are relevant to "Winding" energy. A @{edge->?} is relevant iff its star includes at least one variable node.*/ ??? termOK = erg->termOK^; ??? @{edge->?} = erg->top->edge^; { assert((variable.ne) == erg->top->node.ne); for (i = 0 TO (termOK.ne-1)) { ??? e = @{edge->?}[i]; { assert(e->num == i); termOK[i] = e->exists) && (@{Edge->?}StarIsVariable(e.pa, variable); } } } } /* END DefVar */ PROCEDURE @{Edge->?}StarIsVariable(Place_t @p, bool_vec_t *variable): bool_t == Place_t *b; { Node_t u = OrgV(a); Node_t v = OrgV(NextE(a)); { if ((variable[u->num]) || (variable[v->num])) { return TRUE; } else { b = a; do { Node_t w = OrgV(PrevE(b)); { if (variable[w->num]){ return TRUE;} } b = NextF(b) } while (b != a); return FALSE; } } } /* END @{Edge->?}StarIsVariable */ void SELF_Eval( SELF_T erg; Coords_t *c; double *e; bool_t grad; Gradient *eDc; ) { int NV = erg->top->node.ne; ??? NE = erg->top->NE; ??? termOK = erg->termOK^; ??? term = erg->term^; ??? K = erg->K; ??? rDpw = erg->rDpw^; ??? sDpw = erg->sDpw^; { e = 0.0; /* Clear gradient accumulators */ for (i = 0; i < NV; i++){ eDc[i] = (r4_t){0.0, ..}; } /* Enumerate @{edge->?}s and compute @{edge->?} sums: */ for (i = 0; i < NE; i++) { if (termOK[i]) { AddTerm(term[i], c, K, grad, e, eDc, rDpw, sDpw) } } } } /* END Eval */ void AddTerm( Term *term; Coords_t *c; double K; bool_t grad; VAR /*IO*/ e: double; VAR /*IO*/ eDc: Gradient; VAR rDpw, sDpw: Coords3D_t; /* Work areas. */ ) /* Adds one term of the energy to "e". If "grad" is set, also adds the gradient of that term to "eDc". */ double r, s; /* Radial and perimetral sums for term. */ rDpu, rDpv: r3_t; /* Derivatives of "r" wrt @{edge->?} endpoints. */ sDpu, sDpv: r3_t; /* Derivatives of "s" wrt @{edge->?} endpoints. */ double t; /* An energy term, corresponding to a single @{edge->?}. */ double tDr, tDs; /* Derivatives of "t" w.r.t. "r" and "s". */ double SNorm, RNorm; /* Normalization factors for "r" and "s". */ CONST double Epsilon = 1.0d-20; /* To avoid divide by zero. */ double Pi = M_PI; /* Pi */ double HfPi = 1.5707963267948966; /* Pi/2 */ { ??? un = term.un; pu == SUBARRAY(c[un], 0, 3); double vn = term.vn, pv == SUBARRAY(c[vn], 0, 3); double h = r3_sub(pv, pu); double wn = term.wn^; double ex = term.ex^; double N = FLOAT((wn.ne), double); { void Compute_r_s() /* Returns in "r" and "s" the sums corresponding to the given term of the energy. Also, if "grad" is set, computes the gradients "rDpu", "rDPv", "rDpw[k]" of "r" relative to the 3D coordinates of relevant nodes, and similarly for "s". Also defines the geometry-independent constants "RNorm" and "SNorm", such that a regular @{edge->?} star of height "h" and radius "r" has "r == RNorm·h^2·b^2" and "s == SNorm·h^2·b^2". */ uint *kx, xn; px: r3_t; gaps: NAT; { r = Epsilon; s = Epsilon; gaps = 0; if (grad) { rDpu = (r3_t){0.0,..}; rDpv = (r3_t){0.0,..}; sDpu = (r3_t){0.0,..}; sDpv = (r3_t){0.0,..}; for (i = 0 TO (wn.ne-1)) { rDpw[i] = (r3_t){0.0,..}; sDpw[i] = (r3_t){0.0,..} } } kx = (wn.ne-1); xn = wn[kx]; px = SUBARRAY(c[xn], 0, 3); for (ky = 0 TO (wn.ne-1)) { ??? yn = wn[ky]; ??? py = SUBARRAY(c[yn], 0, 3); double fy = r3_sub(py, pu); double ry = LR3Extras.Cross(h, fy); double rb = LR3.Dot(ry,ry); double gy = r3_sub(py, px); double sy = LR3Extras.Cross(h, gy); double sb = LR3.Dot(sy,sy) { r = r + rb; if (ex[ky]){ s = s + sb }else{ gaps++; } if (grad) { ??? rbDry = r3_scale(2.0, ry); double rbDfy = LR3Extras.Cross(rbDry, h); double rbDh = LR3Extras.Cross(fy, rbDry); { if (Debug) { PrL("rb == ", rb); PrEOL(); PrV("rbDfy == ", rbDfy); PrEOL(); PrV("rbDh == ", rbDh); PrEOL(); } rDpw[ky] = r3_add(rDpw[ky], rbDfy); rDpu = r3_sub(rDpu, r3_add(rbDfy, rbDh)); rDpv = r3_add(rDpv, rbDh); if (ex[ky]) { ??? sbDsy = r3_scale(2.0, sy); double sbDgy = LR3Extras.Cross(sbDsy, h); double sbDh = LR3Extras.Cross(gy, sbDsy); { if (Debug) { PrL("sb == ", sb); PrEOL(); PrV("sbDgy == ", sbDgy); PrEOL(); PrV("sbDh == ", sbDh); PrEOL(); } sDpw[ky] = r3_add(sDpw[ky], sbDgy); sDpw[kx] = r3_sub(sDpw[kx], sbDgy); sDpu = r3_sub(sDpu, sbDh); sDpv = r3_add(sDpv, sbDh); } } } } kx = ky; xn = yn; px = py; } } if (Debug) { PrL("r == ", r); PrEOL(); PrV("rDpu == ", rDpu); PrEOL(); PrV("rDpv == ", rDpv); PrEOL(); PrL("s == ", s); PrEOL(); PrV("sDpu == ", sDpu); PrEOL(); PrV("sDpv == ", sDpv); PrEOL(); PrEOL(); } RNorm = N; if (gaps == 0) { /* @{Edge->?} is interior. */ /* Ideally, winding number should be ±1. */ ??? sn = Math.sin(Pi/N); { SNorm = 4.0*N*sn*sn } } else { assert(gaps < (wn.ne)); /* @{Edge->?} is on border. */ /* Winding number should be ±1/2, with fencepost correction. */ ??? G = ((double)gaps); ??? sn = Math.sin(HfPi/(N-G)); { SNorm = 4.0*(N-G)*sn*sn } } } Compute_r_s; void Compute_t_from_r_s() /* Returns in "t" the energy term corresponding to an @{edge->?} with sums "r" and "s" Also, if "grad" is true, stores in "tDr" and "tDs" the derivatives of the term relative to those sums. */ { ??? R = r/RNorm; ??? S = s/SNorm; ??? f = R/S; ??? g = S/R; ??? z = f + g; { t = K * (z - 2.0); if (Debug) { PrL("R == ", R); PrL("S == ", S); PrL("t == ", t); PrEOL(); } if (grad) { ??? zDr = (1.0/S - g/R)/RNorm; double zDs = (1.0/R - f/S)/SNorm; { tDr = K * zDr; tDs = K * zDs } } else { tDr = 0.0; tDs = 0.0; } } } Compute_t_from_r_s; void Distribute_tDr_tDs() /* Accumulates in "eDc" the gradient of an energy term "t" relative to the nodes in the star of the corresponding @{edge->?} "Edg(a)", given the derivatives "tDr" and "tDs" of the term relative to the edge sums "r" and "s". */ void AddGradientToNode(vn: NAT; rDpv, sDpv: r3_t) /* Adds to "eDc" the contribution due to node "vn". */ { ??? eDcv = eDc[vn]; { eDcv[0] = eDcv[0] + tDr * rDpv[0] + tDs * sDpv[0]; eDcv[1] = eDcv[1] + tDr * rDpv[1] + tDs * sDpv[1]; eDcv[2] = eDcv[2] + tDr * rDpv[2] + tDs * sDpv[2] } } AddGradientToNode; { AddGradientToNode(un, rDpu, sDpu); AddGradientToNode(vn, rDpv, sDpv); for (k = 0 TO (wn.ne-1)) { AddGradientToNode(wn[k], rDpw[k], sDpw[k]) } } Distribute_tDr_tDs; { Compute_r_s(); Compute_t_from_r_s(); e = e + t; if (grad){ Distribute_tDr_tDs();} } } } /* END AddTerm */ PROCEDURE Name(<*UNUSED);erg: T) : char *== { return "Winding()"; } /* END Name */ <*UNUSED); void PrI(prefix: char *; x: INTEGER) { fprintf(stderr, " "); fprintf(stderr, prefix); fprintf(stderr, Fmt.Pad(Fmt.Int(x), 12)); } /* END PrI */ void PrL(prefix: char *; x: double) { fprintf(stderr, " "); fprintf(stderr, prefix); fprintf(stderr, Fmt.Pad(Fmt.LongReal(x, style = Fmt.Style.Fix, prec = 8), 22) ); } /* END PrL */ void PrV(prefix: char *; x: r3_t) { fprintf(stderr, " "); fprintf(stderr, prefix); for (i = 0; i < 3; i++) { fprintf(stderr, Fmt.Pad(Fmt.LongReal(x[i], style = Fmt.Style.Fix, prec = 8), 21) & " " ) } } /* END PrV */ void PrEOL() { fprintf(stderr, "\n"); } /* END PrEOL */ { } WindingEnergy. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/MakeAdjacencyMatrix.c /* See {MakeAdjacencyMatrix.h} */ // #INCLUDE /* This program implements the ShortestPath Algorithm from R. Floyd on Communications of the ACM, Volume 5, Number 6, June, 1962, pag 345 Algorithm 97 SHORTEST PATH Robert W. Floyd Procedure --------- shortest path(m,n); value n; integer n; array m; Comments -------- Initially m[i,j] is the length of a direct link from point i of a network to point j. If no direct link exists, m[i,j] is initially 10^{10}. At completion, m[i,j] is the length of the shortest path from i to j. If nome exists, m[i,j] is 10^{10}. begin integer i,j,k; real inf,s; inf = 10^{10}; for i= 1 step 1 until n do for j= 1 step 1 until n do if m[j,i] < inf then for k= 1 step 1 until n do if m[i,k] < inf then begin s= m[j,i] + m[i,k]; if s < m[j,k] then m[j,k] = s end end shortest path */ #define MakeAdjacencyMatrix_C_author \ "Created by L. P. Lozada, ca. 1999.\n" \ "Modified by L.A.P.Lozada on 99-11-02." #include #include #include // #INCLUDE TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ } double AdjacencyMatrix = ARRAY OF double_vec_t; double inf = Math.pow(10.0,10.0); VAR Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) double *max; m : REF AdjacencyMatrix; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { m = MakeAdjacencyMatrix(top); fprintf(stderr, "\nInput of the ShortestPath Algorithm: " \ o->inFile & ".tp\n"); PrintHalfMatrix(m,top->node.ne); ShortestPath(m,top->node.ne); fprintf(stderr, "\nOutput of the ShortestPath Algorithm\n" & "\n"); PrintHalfMatrix(m,top->node.ne); max = FindMaxDistance(m,top->node.ne); fprintf(stderr, "\nMax Distance: " & Fmt.LongReal(max) & "\n"); return 0; } AdjacencyMatrix *MakeAdjacencyMatrix(ElemTableRec_t *top, )== REF ARRAY OF double_vec_t m ; v: REF ARRAY OF INTEGER; { m = NEW(REF ARRAY OF double_vec_t, top->node.ne, top->node.ne); for (i = 0; i < top->node.ne; i++) { for (j = 0; j < top->node.ne; j++) { m[i,j] = inf; } } for (i = 0; i < top->node.ne; i++) { ??? a = top->node[i]; ??? star = Triangulation.Neighbors(a; with (top), double nv = Triangulation->numberNeighborNode(star) ){ m[i,i] = 0.0; v = NEW(REF ARRAY OF INTEGER, nv); for (k = 0; k < nv; k++) { v[k] = star[k]->num; m[i,v[k]] = 1.0; m[v[k],i] = 1.0; } } } return m; } /* END MakeAdjacencyMatrix */ /* UNUSED */ PROCEDURE PrintAdjacencyMatrix(*m : REF AdjacencyMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.LongReal(m[i,j]) & " "); } } fprintf(stderr, "\n"); } } /* END PrintAdjacencyMatrix */ PROCEDURE PrintHalfMatrix(*m : REF AdjacencyMatrix; n: INTEGER) { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] == inf) { fprintf(stderr, "# "); } else { fprintf(stderr, Fmt.LongReal(m[i,j]) & " "); } } fprintf(stderr, "\n"); } } /* END PrintHalfMatrix */ double FindMaxDistance( *m : REF AdjacencyMatrix; INTEGER n; ) max = 0.0; { for (i = 0; i < n; i++){ for (j = 0; j <= (i); j++) { if (m[i,j] > max) { max = m[i,j]; } } } return max; } /* END FindMaxDistance */ PROCEDURE ShortestPath(VAR m : REF AdjacencyMatrix; n : INTEGER) double *s; { for (i = 0; i < n; i++){ for (j = 0; j < n; j++) { if (m[i,j] < inf) { for (k = 0; k < n; k++) { if (m[i,k] < inf) { s = m[j,i] + m[i,k]; if (s < m[j,k]){ m[j,k] = s; } } } } } } } ShortestPath; Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeAdjacencyMatrix" \ " -inFile \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } MakeAdjacencyMatrix. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Anaglyphs.c #define PROG_NAME "Anaglyphs" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Anaglyphs_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " #include #include #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // #INCLUDE /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ TYPE double FourNodes_t = RECORD u, v, w, x: uint; } typedef struct Options_t { char *inFileTp; inFileSt3: char *; char *outFile; bool_t wire; bool_t all; bool_t texture; bool_t silhouette;/* TRUE draws the silhouette walls */ REAL opacity; /* walls; Transparent (opacity==1) Opaque (opacity==0)*/ } bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { assert(d!=0.0); if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ void DoIt() { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToTaMa(o->inFileTp); ??? rc3 = Tridimensional.ReadState3D(o->inFileSt3); ??? top = tc.top; ??? c3 = rc3^; ??? color1 = "RED"; ??? color2 = "CYAN"; { WritePOVFile(top, c3, o, color1); WritePOVFile(top, c3, o, color2); return 0; } void WritePOVFile(ElemTableRec_t *top, * c3: Tridimensional.Coord3D; Options_t * o; char *color; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(o->outFile & color & ".inc"); { fprintf(wr, "// Include File: <" & o->outFile & ".inc>\n"); WritePOV(wr, top, c3, o, color); fclose(wr) } } /* END WritePOVFile */ void WritePOV( FILE *wr, *ElemTableRec_t *top; * c3: Coord3D; Options_t * o; char *color; ) double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x computes its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0}; { return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2); { if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; cor: frgb_t; { /* Drawing @{edge->?}s */ if (0 == strcmp(color,"RED"))){ cor = (frgb_t){1.0,0.0,0.0}; } else { cor = (frgb_t){0.0,1.0,1.0} } if ((! (o->wire) && (o->all))) { for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { if ((e->exists) || (o->all)) { ??? o = e.node[0]->num; ??? d = e.node[1]->num; ??? t3 = e.transp; ??? transp = (t3[0] + t3[1] + t3[2]) / 3.0; { WritePOVCylinder(wr,c3[o],c3[d],e.radius,cor,transp); } } } } } if (((o->wire) && (o->all))) { for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; ??? o = e.node[0]->num; ??? d = e.node[1]->num; ??? t = e.transp; double transp = (t[0] + t[1] + t[2]) / 3.0; { if (e->exists) { WritePOVCylinder(wr,c3[o],c3[d],e.radius,cor,transp); } else { WritePOVCylinder(wr,c3[o],c3[d],(e.radius)*0.75,cor,transp); } } } } /* Drawing nodes */ for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { if (((v->exists) && (v.radius > 0.0)) || (o->all)) { ??? t3 = v.transp; ??? transp = (t3[0] + t3[1] + t3[2]) / 3.0; { if (v->exists) { WritePOVSphere(wr,c3[i],v.radius,cor,transp); } else { WritePOVSphere(wr,c3[i],v.radius*0.75,cor,transp); } } } } } if (! o->wire) { /* drawing walls */ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if ((f->exists) || (o->all)) { if (top->der == 3) { ??? a = f.pa; Node_t an = OrgV(a)->num; Node_t bn = OrgV(NextE(a))->num; Node_t cn = OrgV(NextE(NextE(a)))->num; ??? t3 = f.transp; ??? transp = (t3[0] + t3[1] + t3[2]) / 3.0; { if (! o->texture) { WritePOVTriangle(wr,c3[an],c3[bn],c3[cn],cor,transp); } else { WritePOVTriangleTex(wr,c3[an],c3[bn],c3[cn],cor,transp); } } } else if (top->der == 4){ ??? a = f.pa; Node_t an = OrgV(a)->num; Node_t bn = OrgV(NextE(a))->num; Node_t cn = OrgV(NextE(NextE(a)))->num; Node_t dn = OrgV(PrevE(a))->num; ??? t3 = f.transp; ??? transp = (t3[0] + t3[1] + t3[2]) / 3.0; { WritePOVSquare(wr,c3[an],c3[bn],c3[cn],c3[dn],cor,transp); } } } } } if ((o->silhouette) && (top->der == 3)) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; ??? t = o->opacity; { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WritePOVTriangle(wr,c3[un], c3[vn], c3[wn],cor,t); } } } } } fflush(wr); } /* END WritePOV */ void GetOptions (): Options_t == { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt3"); o->inFileSt3 = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } o->wire = argparser_keyword_present(pp, "-wire"); o->all = argparser_keyword_present(pp, "-all"); o->texture = argparser_keyword_present(pp, "-texture"); if ((argparser_keyword_present(pp, "-silhouette"))) { o->silhouette = TRUE; if ((argparser_keyword_present(pp, "-opacity"))) { o->opacity = pp.getNextReal(0.0,1.0); } else { o->opacity = 0.85; } } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Anaglyphs \\\n"); fprintf(stderr," -inFileTp -inFileSt3 \\\n"); fprintf(stderr," [ -outFile ] \\\n"); fprintf(stderr," [ -wire ] [ -all ] [ -texture ] \\\n"); fprintf(stderr," [ -silhouette [ -opacity ] ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt(); } Anaglyphs. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/AngleConse.c /* Programa que calcula os angulos diedrais de walls consecutivas incidentes a cada uma das arestas da triangulacao. */ #define AngleConse_C_author \ "Created by L. P. Lozada, 1999-2000." #include // #INCLUDE // #INCLUDE #include #include #include CONST double Pi = Math.Pi; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ } double @{Edge->?} = Triangulation.edge; double Wall = Triangulation.Wall; double EndPoint = ARRAY [0..1] OF uint; double DRF = REF uint_vec_t; double Tri = RECORD u, v, w: uint; } void WriteCoord(FILE *wr, double x) { fprintf(wr, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 2), 6) & " "); } /* END WriteCoord */ /* UNUSED */ void WritePoint(FILE *wr, r4_t *c) { WriteCoord(wr, c[0]); fprintf(wr, " "); WriteCoord(wr, c[1]); fprintf(wr, " "); WriteCoord(wr, c[2]); fprintf(wr, " "); WriteCoord(wr, c[3]); fprintf(wr, " "); } /* END WritePoint */ /* UNUSED */ Tri ExtremusWall(*f: Wall) { ??? fun = f.node[0]->num; ??? fvn = f.node[1]->num; ??? fwn = f.node[2]->num; Tri tri = Tri{fun, fvn, fwn}; { return tri; } } /* END ExtremusWall */ PROCEDURE Extremus@{Edge->?}(*e: @{Edge->?}) : EndPoint == VAR uint stack[1+1]; { ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { stack.e[0] = eun; stack.e[1] = evn; return stack; } } /* END Extremus@{Edge->?} */ /* UNUSED */ PROCEDURE @{Edge->?}Common(*f1,f2 : Wall) : EndPoint == uint stack[1+1]; n : uint = 0; { for (j = 0; j < 3; j++){ for (i = 0; i < 3; i++) { ??? f1j = f1.node[j]->num; ??? f2i = f2.node[i]->num; { if (f1j == f2i) { stack.e[n] = f1j; n++; } } } } return stack; } /* END @{Edge->?}Common */ void DoIt() sta: Stat.T; DRF drf; uint n; { Stat.Init(sta); Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.Read(o->inFile); ??? top = tc.top; ??? c = tc.c^; { DRF ComputeDegreeRingWalls() VAR drf = NEW(REF uint_vec_t , top->NE); { for (l = 0; l < top->NE; l++) { ??? e = top->edge[l]; ??? fie = CollectWalls(e); { drf^[l] = ((fie^).ne); } } return drf; } ComputeDegreeRingWalls; /* UNUSED */ PROCEDURE CollectIncidentWalls(*e: @{Edge->?}): REF ARRAY OF Tri == uint NT = 0; VAR uint ct; { int NF = top->wall.ne; ??? t = NEW(REF ARRAY OF Tri, NF)^; { for (i = 0; i < NF; i++) { ct = 0; ??? f = top->wall[i]; ??? fun = f.node[0]->num; ??? fvn = f.node[1]->num; ??? fwn = f.node[2]->num; ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { if (((fun==eun) || (fun==evn))){ ct++; } if (((fvn==eun) || (fvn==evn))){ ct++; } if (((fwn==eun) || (fwn==evn))){ ct++; } if (ct == 2) { t[NT] = Tri{fun, fvn, fwn}; NT++; } } } ??? r = NEW(REF ARRAY OF Tri, NT); { r^ = SUBARRAY(t,0,NT); return r; } } } CollectIncidentWalls; Wall_vec_t *CollectWalls(*e: @{Edge->?})== uint NT = 0; VAR uint ct; { int NF = top->wall.ne; ??? t = Wall_vec_new(NF)^; { for (i = 0; i < NF; i++) { ct = 0; ??? f = top->wall[i]; ??? fun = f.node[0]->num; ??? fvn = f.node[1]->num; ??? fwn = f.node[2]->num; ??? eun = e.node[0]->num; ??? evn = e.node[1]->num; { if (((fun==eun) || (fun==evn))){ ct++; } if (((fvn==eun) || (fvn==evn))){ ct++; } if (((fwn==eun) || (fwn==evn))){ ct++; } if (ct == 2) { t[NT] = f; NT++; } } } ??? r = Wall_vec_new(NT); { r^ = SUBARRAY(t,0,NT); return r; } } } CollectWalls; double ComputeAverageDiedralAngle(*fie: REF Wall_vec_t; EndPoint bi; grau: uint) double tetham = 0.0; VAR { ??? fie = fie; ??? de = grau; ??? bi = bi; { for (i = 0; i < de; i++) { ??? f1 = fie[i]; ??? af1 = f1.pa^; ??? f2 = fie[(i+1) % de]; ??? af2 = f2.pa^; ??? bf1 = WallBarycenter(af1,c); double bf2 = WallBarycenter(af2,c); double tetha = Angle(bf1,bf2,bi); { tetham = tetham + tetha; } } tetham = tetham/((double)de); return tetham; } } ComputeAverageDiedralAngle; double Angle(*bf1,bf2 : r4_t; e : EndPoint) double *cos,tethar,tetha; { ??? e0 = e[0], e1 == e[1]; double be = r4_Scale(1.0/2.0, r4_Add(c[e0],c[e1])); double a = r4_Sub(be,bf1); double b = r4_Sub(be,bf2); { cos = r4_Cos(a,b); tethar = sqrt( 2.0*(1.0-cos)); assert(0.0 <= tethar) && ((tethar <= FLOAT(Pi,double))); tetha = (180.0*tethar)/((double)Pi); return tetha; } } Angle; double *tethat, tetham, medio, dif; REAL diff; { drf = NEW(REF uint_vec_t , top->NE); for (l = 0; l < top->NE; l++) { ??? e = top->edge[l]; ??? fie = CollectWalls(e); ??? bi = Extremus@{Edge->?}(e); ??? drf = LAST(fie^)+1; { medio = ComputeAverageDiedralAngle(fie,bi,drf); /* fprintf(Stdio.stdout, "Aresta[" & Fmt.Int(e->num) & "]: " \ " Nodes Extremos: " & Fmt.Int(bi[0]) & "-" \ Fmt.Int(bi[1]) & " , "); fprintf(Stdio.stdout,"DegreeRingWalls: " & Fmt.Int(drf) \ ", Angulo ideal: " & Fmt.LongReal(360.0/FLOAT(drf,double)) & "\n"); fprintf(Stdio.stdout, "Walls Incidentes: \n"); */ dif = fabs(medio - 360.0/FLOAT(drf,double)); diff = FLOAT(dif, REAL); Stat.Accum(sta,diff); /* for(i = 0; i < fie.ne; i++) { ??? fun = fie^[i].node[0]->num; ??? fvn = fie^[i].node[1]->num; ??? fwn = fie^[i].node[2]->num; { fprintf(Stdio.stdout, Fmt.Int(fun) & " " & Fmt.Int(fvn) \ " " & Fmt.Int(fwn) & "\n"); } } fprintf(Stdio.stdout, "Angles consecutives: "); tethat = 0.0; for (j = 0; j < drf; j++) { ??? f1 = fie[j]; ??? af1 == f1.pa^; double f2 = fie[(j+1) % drf], af2 == f2.pa^; double bf1 = WallBarycenter(af1,c); double bf2 = WallBarycenter(af2,c); double tetha = Angle(bf1,bf2,bi); { WriteCoord(stdout,tetha); tethat = tethat + tetha; } } tetham = tethat/((double)drf); fprintf(Stdio.stdout, " ==> Total: " \ Fmt.Pad(Fmt.LongReal(tethat, Fmt.Style.Fix, prec = 1), 5) & " "); fprintf(Stdio.stdout, " ==> Average: " \ Fmt.Pad(Fmt.LongReal(tetham, Fmt.Style.Fix, prec = 1), 5) & "\n"); } fprintf(Stdio.stdout, "\n"); */ } fprintf(stdout, "\nWeight statistics of diference between ideal and average diedral Angle:\n"); Stat.Print(stdout, sta); fprintf(stdout, "\n"); /* drf = ComputeDegreeRingWalls(); n = ComputeDegreeTotal(drf); fprintf(Stdio.stdout, "Degree Ring Walls Total is : " & Fmt.Int(n) & "\n"); */ } return 0; } uint ComputeDegreeTotal(*drf: DRF) n : uint = 0; { for(l = 0; l < drf.ne; l++){ ??? d = drf^[l]; { n = n + d; } } return n; } /* END ComputeDegreeTotal */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: AngleConse" \ " -inFile " \ "\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } AngleConse. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/AutoDodeIco.c #define PROG_NAME "AutoDodeIco" #define PROG_DESC "???" #define PROG_VERS "1.0" #define AutoDodeIco_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program implements the automatic gluing of cells (tetrahedra, triangulated octahedra) for the 4D non-regular polytope: "pentaocta" */ // #INCLUDE #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE TYPE double Row2I = ARRAY[0..1] OF uint; double z4_t = ARRAY[0..3] OF uint; double Shape_t = {Dodecahedron, Icosahedron}; typedef struct Options_t { bool_t detail; bool_t free; Shape_t shape; char *shapeName; } REF ARRAY OF z4_t cell4 ; tetra : REF ARRAY OF ARRAY [0..3] OF Place_t; Options_t o; uint cellnum; /* UNUSED */ void WriteCells(*g: REF ARRAY OF z4_t) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? st = FileWr.Open(o->shapeName); { void WriteNode(x: uint) { fprintf(st, Fmt.Pad(Fmt.Int(x),7)); } WriteNode; void WriteCell(*c: z4_t) { WriteNode(c[0]); fprintf(st, " "); WriteNode(c[1]); fprintf(st, " "); WriteNode(c[2]); fprintf(st, " "); WriteNode(c[3]); } WriteCell; { for(i = 0; i < g.ne; i++) { WriteNode(i); WriteCell(g[i]); fprintf(st, "\n"); } } fclose(st); } } /* END WriteCells */ void DoIt() Place_t GlueTetras(Ti,Tj,Ci,Cj: uint) /* Gluing the tetrahedra Ti with Tj through the free walls Ci and Cj respectively. */ void PrintInfo(case: uint;oi,oj,di,dj: uint) /* Prints information about the three possible cases in the gluing procedure. */ { fprintf(stderr, "case " & Fmt.Int(case) & ": "); fprintf(stderr, Fmt.Int(oi) & " " & Fmt.Int(di)&"\n"); fprintf(stderr, " "); fprintf(stderr, Fmt.Int(oj) & " " & Fmt.Int(dj)&"\n\n"); } PrintInfo; void UngluedInfo(ci,cj,ti,tj: uint) /* Prints information about unglued case in the gluing procedure. This procedure cause the halt of the program. */ { fprintf(stderr, "Not glue this case " & Fmt.Int(ci) & " " \ Fmt.Int(cj) & "\n"); fprintf(stderr, " Tetrahedra " & Fmt.Int(ti) & " " \ Fmt.Int(tj) & "\n"); Process.Exit¦(1); } UngluedInfo; { if (o->detail) { fprintf(stderr,"Ci=="&Fmt.Int(Ci)&" Cj=="&Fmt.Int(Cj)&", "); } IF /* 1 */ double Ci = 0) && (Cj == 0)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 2 */ double Ci = 0) && (Cj == 1)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 3 */ double Ci = 0) && (Cj == 2)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 4 */ double Ci = 0) && (Cj == 3)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 5 */ double Ci = 1) && (Cj == 0)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 6 */ double Ci = 1) && (Cj == 1)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 7 */ double Ci = 1) && (Cj == 2)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 8 */ double Ci = 1) && (Cj == 3)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 9 */ double Ci = 2) && (Cj == 0)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 10 */ double Ci = 2) && (Cj == 1)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 11 */ double Ci = 2) && (Cj == 2)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 12 */ double Ci = 2) && (Cj == 3)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 13 */ double Ci = 3) && (Cj == 0)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 14 */ double Ci = 3) && (Cj == 1)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 15 */ double Ci = 3) && (Cj == 2)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 16 */ double Ci = 3) && (Cj == 3)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } } return tetra[Ti].p[0]; } /* END GlueTetras */ void SetCornersTetra(uint Ti, z4_t row) /* Set the labels "row" in the tetrahedron Ti. */ { Node_t a = OrgV(tetra[Ti].p[0]); double b = OrgV(Clock(tetra[Ti].p[0])); double c = OrgV(PrevE(tetra[Ti].p[1])); double d = OrgV(PrevE(tetra[Ti].p[0])); { a->num = row[0]; b->num = row[1]; c->num = row[2]; d->num = row[3]; } } SetCornersTetra; void EffaceNode(uint Ti, uint nn) /* Set one node onto the tetrahedra "Ti" as non-existing. */ { Node_t a = OrgV(tetra[Ti].p[0]); Node_t b = OrgV(Clock(tetra[Ti].p[0])); Node_t c = OrgV(PrevE(tetra[Ti].p[1])); Node_t d = OrgV(PrevE(tetra[Ti].p[0])); { if (a->num == @{node->?}) { a->exists = FALSE; } if (b->num == @{node->?}) { b->exists = FALSE; } if (c->num == @{node->?}) { c->exists = FALSE; } if (d->num == @{node->?}) { d->exists = FALSE; } } } EffaceNode; PROCEDURE EffaceEdgesOfNode(uint Ti, uint nn) == /* Set all @{edge->?}s incidents in the node "@{node->?}" as non-existing.*/ { Node_t a = OrgV(tetra[Ti].p[0])->num; Node_t b = OrgV(Clock(tetra[Ti].p[0]))->num; Node_t c = OrgV(PrevE(tetra[Ti].p[1]))->num; Node_t d = OrgV(PrevE(tetra[Ti].p[0]))->num; ??? e0 = PWedge(tetra[Ti].p[0]).edge; ??? e1 = PWedge(tetra[Ti].p[2]).edge; ??? e2 = PWedge(NextE(tetra[Ti].p[2])).edge; ??? e3 = PWedge(PrevE(tetra[Ti].p[2])).edge; ??? e4 = PWedge(NextE(tetra[Ti].p[0])).edge; ??? e5 = PWedge(NextE(tetra[Ti].p[1])).edge { if ((a == @{node->?}) || (b == @{node->?})) { e0->exists = FALSE; } if ((c == @{node->?}) || (d == @{node->?})) { e1->exists = FALSE; } if ((a == @{node->?}) || (d == @{node->?})) { e2->exists = FALSE; } if ((a == @{node->?}) || (c == @{node->?})) { e3->exists = FALSE; } if ((b == @{node->?}) || (d == @{node->?})) { e4->exists = FALSE; } if ((b == @{node->?}) || (c == @{node->?})) { e5->exists = FALSE; } } } EffaceEdgesOfNode; void EffaceWallsOfNode(uint Ti, @{node->?}: uint) /* Set all wallse incidents in the node "@{node->?}" as non-existing.*/ { Node_t a = OrgV(tetra[Ti].p[0])->num; Node_t b = OrgV(Clock(tetra[Ti].p[0]))->num; Node_t c = OrgV(PrevE(tetra[Ti].p[1]))->num; Node_t d = OrgV(PrevE(tetra[Ti].p[0]))->num; double f0 = PWedge(tetra[Ti].p[0]).wall; double f1 = PWedge(tetra[Ti].p[1]).wall; double f2 = PWedge(tetra[Ti].p[2]).wall; double f3 = PWedge(tetra[Ti].p[3]).wall; { if ((a == @{node->?}) || (b == @{node->?}) || (d == @{node->?})) { f0->exists = FALSE; } if ((a == @{node->?}) || (b == @{node->?}) || (c == @{node->?})) { f1->exists = FALSE; } if ((a == @{node->?}) || (c == @{node->?}) || (d == @{node->?})) { f2->exists = FALSE; } if ((b == @{node->?}) || (c == @{node->?}) || (d == @{node->?})) { f3->exists = FALSE; } } } EffaceWallsOfNode; bool_t MustBeGlued(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have coherent orientations and must be glued. */ { Node_t a = OrgV(Ti)->num; Node_t ae = OrgV(NextE(Ti))->num; ??? ae_1 = OrgV(PrevE(Ti))->num; Node_t b = OrgV(Tj)->num; Node_t be = OrgV(NextE(Tj))->num; ??? be_1 = OrgV(PrevE(Tj))->num; { if (((a == b) && (ae == be) && (ae_1 == be_1) OR (a == b) && (ae == be_1) && (ae_1 == be))){ return TRUE; } return FALSE } } MustBeGlued; bool_t BadAttribution(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have incoherent orientations. */ { Node_t i0 = OrgV(Ti)->num; ??? i1 = OrgV(NextE(Ti))->num; ??? i2 = OrgV(PrevE(Ti))->num; Node_t j0 = OrgV(Tj)->num; ??? j1 = OrgV(NextE(Tj))->num; ??? j2 = OrgV(PrevE(Tj))->num; { if ((SpinBit(Ti)!=SpinBit(Tj))) { if (((i0 == j0) && (i1 == j2) && (i2 == j1) OR (i0 == j2) && (i1 == j1) && (i2 == j0) OR (i0 == j1) && (i1 == j0) && (i2 == j2) )){ return TRUE } }; if ((SpinBit(Ti) == SpinBit(Tj))) { if (((i0 == j0) && (i1 == j1) && (i2 == j2) OR (i0 == j2) && (i0 == j0) && (i2 == j1) OR (i0 == j1) && (i1 == j2) && (i2 == j0) )){ return TRUE } }; return FALSE } } BadAttribution; void PrintCorners(Tuint i) /* Print the corners of the triangular wall "Ti". */ { Node_t a = OrgV(walls[Ti])->num; Node_t ae = OrgV(NextE(walls[Ti]))->num; ??? ae_1 = OrgV(PrevE(walls[Ti]))->num; { fprintf(stderr, Fmt.Pad(Fmt.Int(a),3) & " " \ Fmt.Pad(Fmt.Int(ae),3) \ " " & Fmt.Pad(Fmt.Int(ae_1),3) & " "); } } PrintCorners; void PrintFreeCorners(number: uint) { for (i = 0; i < number; i++) { for (j = 0; j < 4; j++) { ??? a = tetra[i].p[j]; double d = Octf.DegreeOfWall(a); { if ((d!=1) && (Ppos(a) == NULL)) { fprintf(stderr, "tetra[" & Fmt.Pad(Fmt.Int(i),2) & "," \ Fmt.Pad(Fmt.Int(j),2) & "]\n") } } } } } PrintFreeCorners; REF ARRAY OF EightPlaces_t poly ; id : uint = 0; count : uint = 1; walls : REF Place_vec_t; glues : REF ARRAY OF z4_t; { o = GetOptions(); if ( o->shape == Shape_Dodecahedron) { cellnum = 60; cell4 = NEW(REF ARRAY OF z4_t, cellnum); } else if (o->shape == Shape_Icosahedron){ cellnum = 20; cell4 = NEW(REF ARRAY OF z4_t, cellnum); } poly = NEW(REF ARRAY OF EightPlaces_t,cellnum); tetra = NEW(REF ARRAY OF ARRAY [0..3] OF Place_t,cellnum); Place_vec_t walls = Place_vec_new( 4*cellnum); glues = NEW(REF ARRAY OF z4_t, 2*cellnum); /* Create topological tetrahedra */ for (i = 0; i < cellnum; i++) { poly[i] = MakeTetraTopo(1,1); } /* Create the tetrahedra */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { tetra[i].p[j] = poly[i,j]; assert(Ppos(tetra[i].p[j]) == NULL); } } /* cells with corners perfectly assigments */ if (o->shape == Shape_Dodecahedron) { cell4[ 0]=(z4_t){{100,500, 0, 1}}; cell4[ 1]=(z4_t){{100,500, 1, 4}}; cell4[ 2]=(z4_t){{100,500, 4, 7}}; cell4[ 3]=(z4_t){{100,500, 7, 2}}; cell4[ 4]=(z4_t){{100,500, 2, 0}}; cell4[ 5]=(z4_t){{500,101, 0, 1}}; cell4[ 6]=(z4_t){{500,101, 1, 5}}; cell4[ 7]=(z4_t){{500,101, 5, 8}}; cell4[ 8]=(z4_t){{500,101, 8, 3}}; cell4[ 9]=(z4_t){{500,101, 3, 0}}; cell4[ 10]=(z4_t){{500,102, 2, 0}}; cell4[ 11]=(z4_t){{500,102, 0, 3}}; cell4[ 12]=(z4_t){{500,102, 3, 9}}; cell4[ 13]=(z4_t){{500,102, 9, 6}}; cell4[ 14]=(z4_t){{500,102, 6, 2}}; cell4[ 15]=(z4_t){{103,500, 6, 2}}; cell4[ 16]=(z4_t){{500,103, 7, 2}}; cell4[ 17]=(z4_t){{103,500, 7, 13}}; cell4[ 18]=(z4_t){{103,500, 13, 12}}; cell4[ 19]=(z4_t){{500,103, 6, 12}}; cell4[ 20]=(z4_t){{500,104, 1, 4}}; cell4[ 21]=(z4_t){{500,104, 4, 10}}; cell4[ 22]=(z4_t){{500,104, 10, 11}}; cell4[ 23]=(z4_t){{500,104, 11, 5}}; cell4[ 24]=(z4_t){{500,104, 5, 1}}; cell4[ 25]=(z4_t){{500,105, 9, 3}}; cell4[ 26]=(z4_t){{500,105, 3, 8}}; cell4[ 27]=(z4_t){{500,105, 8, 14}}; cell4[ 28]=(z4_t){{500,105, 14, 15}}; cell4[ 29]=(z4_t){{500,105, 15, 9}}; cell4[ 30]=(z4_t){{500,106, 12, 6}}; cell4[ 31]=(z4_t){{500,106, 6, 9}}; cell4[ 32]=(z4_t){{500,106, 9, 15}}; cell4[ 33]=(z4_t){{500,106, 15, 18}}; cell4[ 34]=(z4_t){{500,106, 18, 12}}; cell4[ 35]=(z4_t){{500,107, 4, 7}}; cell4[ 36]=(z4_t){{500,107, 7, 13}}; cell4[ 37]=(z4_t){{500,107, 13, 16}}; cell4[ 38]=(z4_t){{500,107, 16, 10}}; cell4[ 39]=(z4_t){{500,107, 10, 4}}; cell4[ 40]=(z4_t){{108,500, 5, 8}}; cell4[ 41]=(z4_t){{108,500, 8, 14}}; cell4[ 42]=(z4_t){{108,500, 14, 17}}; cell4[ 43]=(z4_t){{108,500, 17, 11}}; cell4[ 44]=(z4_t){{108,500, 11, 5}}; cell4[ 45]=(z4_t){{109,500, 18, 12}}; cell4[ 46]=(z4_t){{109,500, 12, 13}}; cell4[ 47]=(z4_t){{109,500, 13, 16}}; cell4[ 48]=(z4_t){{109,500, 16, 19}}; cell4[ 49]=(z4_t){{109,500, 19, 18}}; cell4[ 50]=(z4_t){{500,110, 18, 15}}; cell4[ 51]=(z4_t){{500,110, 15, 14}}; cell4[ 52]=(z4_t){{500,110, 14, 17}}; cell4[ 53]=(z4_t){{500,110, 17, 19}}; cell4[ 54]=(z4_t){{500,110, 19, 18}}; cell4[ 55]=(z4_t){{111,500, 10, 11}}; cell4[ 56]=(z4_t){{111,500, 11, 17}}; cell4[ 57]=(z4_t){{111,500, 17, 19}}; cell4[ 58]=(z4_t){{111,500, 19, 16}}; cell4[ 59]=(z4_t){{111,500, 16, 10}}; } else if (o->shape == Shape_Icosahedron){ cell4[ 0]=(z4_t){{100, 0, 1, 2}}; cell4[ 1]=(z4_t){{ 0,100, 1, 4}}; cell4[ 2]=(z4_t){{ 2,100, 0, 3}}; cell4[ 3]=(z4_t){{100, 4, 0, 5}}; cell4[ 4]=(z4_t){{100, 3, 2, 8}}; cell4[ 5]=(z4_t){{ 1,100, 2, 6}}; cell4[ 6]=(z4_t){{ 5,100, 4, 10}}; cell4[ 7]=(z4_t){{100, 1, 4, 7}}; cell4[ 8]=(z4_t){{ 8,100, 3, 9}}; cell4[ 9]=(z4_t){{100, 0, 3, 5}}; cell4[ 10]=(z4_t){{100, 6, 1, 7}}; cell4[ 11]=(z4_t){{100, 10, 5, 9}}; cell4[ 12]=(z4_t){{100, 9, 8, 11}}; cell4[ 13]=(z4_t){{ 2,100, 8, 6}}; cell4[ 14]=(z4_t){{ 7,100, 6, 11}}; cell4[ 15]=(z4_t){{ 9,100, 10, 11}}; cell4[ 16]=(z4_t){{100, 4, 10, 7}}; cell4[ 17]=(z4_t){{100, 3, 9, 5}}; cell4[ 18]=(z4_t){{100, 11, 7, 10}}; cell4[ 19]=(z4_t){{ 8,100, 11, 6}}; } /* set the labels for each tetrahedra */ for (i = 0; i < cellnum; i++) { SetCornersTetra(i,cell4[i]); } /* set the non-existing nodes,@{edge->?}s and walls.*/ if (o->shape == Shape_Dodecahedron) { for (i = 0; i < cellnum; i++) { EffaceNode(i,500); EffaceEdgesOfNode(i,500); EffaceWallsOfNode(i,500); for (j = 100; j < 112; j++) { EffaceNode(i,j); EffaceEdgesOfNode(i,j); } } } else if (o->shape == Shape_Icosahedron){ for (i = 0; i < cellnum; i++) { EffaceNode(i,100); EffaceEdgesOfNode(i,100); EffaceWallsOfNode(i,100); } } /*WriteCells(cell4);*/ /* builds the table of walls for choose which tetrahedra must be gluing. */ if (o->detail) { fprintf(stderr, "C id table wall\n"); fprintf(stderr, "-------------------------\n"); } for (i = 0; i < cellnum; i++) { if (o->detail) { fprintf(stderr, Fmt.Int(i) & "\n"); } for (k = 0; k < 4; k++) { walls[(4*i)+k] = tetra[i].p[k]; if (o->detail) { fprintf(stderr," "& Fmt.Pad(Fmt.Int(id),4)&" "); id++; PrintCorners((4*i)+k); fprintf(stderr, " " & Fmt.Int(k) & "\n"); } } } /* computing which cells must be gluing. */ for(k = 0; k < walls.ne; k++) { for (l = k+1 TO LAST(walls^)) { for (m = 0; m < 3; m++) { ??? e = NextEK(walls[l],m); { if ((MustBeGlued(walls[k],e))) { if (o->detail) { fprintf(stderr, Fmt.Int(count) & "\n"); fprintf(stderr, "must be gluing: walls[" & Fmt.Int(k) \ "] with "); fprintf(stderr, "walls[" & Fmt.Int(l) &"]\n"); } ??? kc = k % 4; ??? kt = k DIV 4; ??? lc = l % 4; ??? lt = l DIV 4; { if (o->detail) { fprintf(stderr, " tetra["&Fmt.Int(kt) & "," \ Fmt.Int(kc) & "] and tetra[" & Fmt.Int(lt) & "," \ Fmt.Int(lc) & "]\n\n"); } glues[count-1] = (z4_t){{kt,lt,kc,lc}}; count++; if ((BadAttribution(walls[k],e))) { fprintf(stderr, "Bad Attribution " & " tetra["& Fmt.Int(kt) &"] and tetra[" & Fmt.Int(lt) & "]\n"); } } } } } } } /* Do the automatic gluing of tetrahedra */ for(i = 0; i < glues.ne; i++) { ??? c = glues[i]; { if (c!=(z4_t){{0,0,0,0}}) { EVAL GlueTetras(c[0],c[1],c[2],c[3]); } } } if (o->free){ fprintf(stderr,"Listing free corners\n"); PrintFreeCorners(cellnum) } /* Set the origins. */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { ??? a = tetra[i].p[j]; Place_t b = NextE(a); Place_t c = PrevE(a); { SetOrgAll(a,OrgV(a)); SetOrgAll(b,OrgV(b)); SetOrgAll(c,OrgV(c)); } } } /* Builds and writes the topology. */ if ( o->shape == Shape_Dodecahedron) { fprintf(stderr, "Building the topology of dodecahedron:\n"); } else if (o->shape == Shape_Icosahedron){ fprintf(stderr, "Building the topology of icosahedron:\n"); } ??? a = tetra[cellnum-1].p[0]; double top = MakeElemTable(a); double c = GenCoords(top)^; { /* seting the elements root for edges and walls.*/ for (i = 0; i < top.wall.ne; i++) { ??? f = top.wall[i]; { f->root = f->num; } } for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i]; { e->root = e->num; } } WriteTopology(o->shapeName, top, "Created by AutoDodeIco: " & o->shapeName & ".tp on " \ Today()); WriteMaterials(o->shapeName, top, "Created by AutoDodeIco: " & o->shapeName & ".ma on " \ Today()); WriteState(o->shapeName, top, c, "Created by AutoDodeIco: " & o->shapeName & ".st on " \ Today() &"\nRandom Geometry"); } } DoIt; /* UNUSED */ void PrintRow4I(m: z4_t) /* Print an array of four integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & " " \ Fmt.Int(m[2]) & " " & Fmt.Int(m[3]) & "\n"); } /* END PrintRow4I */ /* UNUSED */ void PrintRow2I(m: Row2I) /* Print an array of two integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & "\n"); } /* END PrintRow2I */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "icosahedron"))) { o->shape = Shape_Icosahedron } else if (0 == strcmp(o->shapeName, "dodecahedron"))){ o->shape = Shape_Dodecahedron } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n"); } o->detail = argparser_keyword_present(pp, "-detail"); o->free = argparser_keyword_present(pp, "-free"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: AutoDodeIco \\\n" \ " -shape { icosahedron | dodecahedron } \\\n" \ " [ -free ] [ -detail ] \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } AutoDodeIco. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/AutoGluing.c #define PROG_NAME "AutoGluing" #define PROG_DESC "???" #define PROG_VERS "1.0" #define AutoGluing_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program implements the automatic gluing of cells (tetrahedra, triangulated octahedra) for the 4D regular and convex polytopes: 5cell, 16cell and 24cell. */ #include #include #include // #INCLUDE #include // #INCLUDE #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE TYPE double Shape_t = {cell5, cell16, cell24}; typedef struct Options_t { char *inFile; Shape_t shape; char *shapeName; bool_t draw; bool_t detail; bool_t fixed; } double Row2I = ARRAY[0..1] OF uint; double z4_t = ARRAY[0..3] OF uint; double Row6I = ARRAY[0..5] OF uint; double CARDI = uint; double Geom = RECORD uint DER; /* Degree @{Edge->?} Ring */ uint nV; /* Number of node */ uint nE; /* Number of @{edge->?}s */ uint nF; /* Number of walls */ c : REF Coords_t; @{edge->?}: REF ARRAY OF uint_vec_t; wall: REF ARRAY OF uint_vec_t; } CONST double AlphaChars = Mis.AlphaChars; double INIT_STACK_SIZE = 700; VAR Stack4 = NEW(REF ARRAY OF z4_t, INIT_STACK_SIZE); /* stack of z4_t.*/ Stack6 = NEW(REF ARRAY OF Row6I, INIT_STACK_SIZE); /* stack of Row6I.*/ Stack = NEW(REF ARRAY OF CARDI, INIT_STACK_SIZE); /* stack of cardinal.*/ cellnum, tpst : uint = 0; /* tops for the stacks above. */ cell4 = NEW(REF ARRAY OF z4_t, INIT_STACK_SIZE); cell6 = NEW(REF ARRAY OF Row6I, INIT_STACK_SIZE); tetra : REF ARRAY OF ARRAY [0..3] OF Place_t; octa : REF ARRAY OF EightPlaces_t; Geom ReadWire4(char *name) <* FATAL Rd.Failure, Thread.Alerted, FloatMode.Trap, Lex.Error, OSError.E); VAR Geom geom; char *cmt; { FILE *rw = open_read(fileName, TRUE); /* {name}.{w4} */ { cmt = filefmt_read_comment(rw, '#'); /* Element counts: */ Lex.Skip(rw, cs = AlphaChars); geom.DER = fget_int32(rw); Lex.Skip(rw); cmt = filefmt_read_comment(rw, '#'); Lex.Skip(rw, cs = AlphaChars); geom.NV = fget_int32(rw); geom.c = NEW(REF Coords_t, geom.NV); /* Read node data coordinates: */ for (j = 0; j < geom.NV; j++) { Lex.Skip(rw); ??? cv = geom.c[j]; { cv[0] = Lex.LongReal(rw); Lex.Skip(rw); cv[1] = Lex.LongReal(rw); Lex.Skip(rw); cv[2] = Lex.LongReal(rw); Lex.Skip(rw); cv[3] = Lex.LongReal(rw); } } Lex.Skip(rw, cs = AlphaChars); geom.NE = fget_int32(rw); Lex.Skip(rw); /* Create @{edge->?} records */ geom.edge = NEW(REF ARRAY OF uint_vec_t , geom.NE,2); /* Read @{edge->?} extremus */ for (j = 0; j < geom.NE; j++) { Lex.Skip(rw); ??? ee = geom.edge[j]; { ee[0] = fget_int32(rw); Lex.Skip(rw); ee[1] = fget_int32(rw); } } Lex.Skip(rw, cs = AlphaChars); geom.NF = fget_int32(rw); Lex.Skip(rw); /* Create wall records */ geom.wall = NEW(REF ARRAY OF uint_vec_t , geom.NF,geom.DER); /* Read wall extremus */ for (j = 0; j < geom.NF; j++) { Lex.Skip(rw); ??? ff = geom.wall[j]; { for (k = 0; k < geom.DER; k++) { ff[k] = fget_int32(rw); Lex.Skip(rw); } } } fclose(rw); return geom; } } /* END ReadWire4 */ void DoIt() REF ARRAY OF ARRAY OF uint_vec_t cells ; e1 : REF ARRAY OF INTEGER; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? g = ReadWire4(o->shapeName); { uint ComputeTips(x,y,z,w: uint) REF uint_vec_t p ; k: uint = 0; { p = NEW(REF uint_vec_t ,3); ??? O = x; ??? D = z; { for (j = 0; j < g.NF; j++) { ??? f = g.wall[j]; ??? a = f[0]; ??? b = f[1]; ??? c = f[2]; { if (( (O == a)) && (D == b)){ p[k] = c; k++; } else if ((O == a) && (D == c)){ p[k] = b; k++; } else if ((O == b) && (D == a)){ p[k] = c; k++; } else if ((O == b) && (D == c)){ p[k] = a; k++; } else if ((O == c) && (D == a)){ p[k] = b; k++; } else if ((O == c) && (D == b)){ p[k] = a; k++; } } } for (m = 0; m < 3; m++) { if ((p[m]!=w) && (p[m]!=x)) { if ((AreAdjacents(p[m],y)) && (AreAdjacents(p[m],z))) { return p[m]; } } } } return 1000; } ComputeTips; bool_t AreAdjacents(a,b: uint) /* Decides if exists some @{edge->?} with tips "a" and "b". */ { for (m = 0; m < g.NE; m++) { ??? E = g.edge[m]; ??? EO = E[0]; ??? ED = E[1]; { if ((( (a == EO)) && (b == ED) OR ( (a == ED)) && (b == EO))){ return TRUE; } } } return FALSE; } AreAdjacents; Place_t GlueTetras(Ti,Tj,Ci,Cj: uint) /* Gluing the tetrahedra Ti with Tj through the free walls Ci and Cj respectively. */ void PrintInfo(case: uint;oi,oj,di,dj: uint) /* Prints information about the three possible cases in the gluing procedure. */ { fprintf(stderr, "case " & Fmt.Int(case) & ": "); fprintf(stderr, Fmt.Int(oi) & " " & Fmt.Int(di)&"\n"); fprintf(stderr, " "); fprintf(stderr, Fmt.Int(oj) & " " & Fmt.Int(dj)&"\n\n"); } PrintInfo; void UngluedInfo(ci,cj,ti,tj: uint) /* Prints information about unglued case in the gluing procedure. This procedure cause the halt of the program. */ { fprintf(stderr, "Not glue this case " & Fmt.Int(ci) & " " \ Fmt.Int(cj) & "\n"); fprintf(stderr, " Tetrahedra " & Fmt.Int(ti) & " " \ Fmt.Int(tj) & "\n"); Process.Exit¦(1); } UngluedInfo; { if (o->detail) { fprintf(stderr,"Ci=="&Fmt.Int(Ci)&" Cj=="&Fmt.Int(Cj)&", "); } IF /* 1 */ double Ci = 0) && (Cj == 0)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 2 */ double Ci = 0) && (Cj == 1)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 3 */ double Ci = 0) && (Cj == 2)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 4 */ double Ci = 0) && (Cj == 3)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 5 */ double Ci = 1) && (Cj == 0)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 6 */ double Ci = 1) && (Cj == 1)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 7 */ double Ci = 1) && (Cj == 2)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 8 */ double Ci = 1) && (Cj == 3)) { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 9 */ double Ci = 2) && (Cj == 0)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 10 */ double Ci = 2) && (Cj == 1)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 11 */ double Ci = 2) && (Cj == 2)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 12 */ double Ci = 2) && (Cj == 3)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 13 */ double Ci = 3) && (Cj == 0)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 14 */ double Ci = 3) && (Cj == 1)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 15 */ double Ci = 3) && (Cj == 2)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 16 */ double Ci = 3) && (Cj == 3)) { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3] { int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } } return tetra[Ti].p[0]; } GlueTetras; PROCEDURE CorretAttribution(peak: REF uint_vec_t) : REF ARRAY OF Row2I == /* atribui de maneira correta os nodes extremos de um tetraedro */ VAR Stack2 : REF ARRAY OF Row2I; /* stack for peaks */ topo : uint = 0; r : Row2I; Ext : REF ARRAY OF Row2I; guardar: uint; bool_t Present2(array : Row2I) /* Return TRUE if "array" its on the stack, FALSE c.c. */ uint nstack1 = topo; e1 : REF uint_vec_t; st : REF uint_vec_t; { e1 = NEW(REF uint_vec_t ,2); st = NEW(REF uint_vec_t ,2); for (i = 0; i < 2; i++) { e1[i] = array[i]; } Mis.Sort(1,e1); while (nstack1 > 0) { nstack1 = nstack1 - 1; for (i = 0; i < 2; i++) { st[i] = Stack2[nstack1][i]; } Mis.Sort(1,st); if (st^ == e1^){ return TRUE; } } return FALSE; } Present2; void Save2(array : Row2I) /* Saves the "array" on the stack "Stack2". */ { Stack2[topo] = array; topo = topo + 1; } Save2; bool_t Coincide(array : Row2I; chave: uint) { ??? b = array[0]; { if (b == chave){ return TRUE; } return FALSE; } } Coincide; bool_t Candidate(array : Row2I; chave: uint) /* Decides if the array "array" is a possivel candidate to be consider. This is, if any element of the array is equal to the key "chave" then this procedure return TRUE, FALSE c.c. */ { ??? b = array[0]; ??? c = array[1]; { if ((b == chave) || (c == chave)){ return TRUE; } return FALSE; } } Candidate; bool_t Same(a,b: Row2I) /* Decides if the arrays "a" and "b" are the same without consider the order between then. */ { ??? a0 = a[0]; ??? a1 = a[1]; ??? b0 = b[0]; ??? b1 = b[1]; { if (((a0 == b1) && (a1 == b0)) || ((a0 == b0) && (a1 == b1))) { return TRUE; } return FALSE; } } Same; Row2I Report(chave: uint; indice: uint) { for (j = 0; j < topo; j++) { if (indice == 1) { if ((! Same(Stack2[j],Ext[0]))) { ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } else if (indice == 2){ if ((! Same(Stack2[j],Ext[0])) && (NOT Same(Stack2[j],Ext[1]) )){ ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } else if (indice == 3){ if ((! Same(Stack2[j],Ext[0])) && (NOT Same(Stack2[j],Ext[1]) ) && (NOT Same(Stack2[j],Ext[2]))){ ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } else if (indice == 4){ if ((! Same(Stack2[j],Ext[0])) && (NOT Same(Stack2[j],Ext[1]) ) && (NOT Same(Stack2[j],Ext[2]) AND NOT Same(Stack2[j],Ext[3]))) { ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } } return Row2I{0,0}; } Report; { Stack2 = NEW(REF ARRAY OF Row2I, LAST(peak^)+1); Ext = NEW(REF ARRAY OF Row2I, LAST(peak^)+1); for(i = 0; i < peak.ne; i++) { for(j = 0; j < peak.ne; j++) { if ((i!=j) && (AreAdjacents(peak[i],peak[j]))) { r[0] = peak[i]; r[1] = peak[j]; if ((! Present2(r))){ Save2(r); } } } }; /* Correct assigment of labels for each cell. */ Ext[0] = Stack2[0]; guardar = Ext[0][1]; for(i = 1; i < peak.ne; i++) { Ext[i] = Report(guardar,i); guardar = Ext[i][1]; } return Ext; } CorretAttribution; { /* allocating space for the cell informations to be compute. */ if (o->shape == Shape_cell5) { cells = NEW(REF ARRAY OF ARRAY OF uint_vec_t , g.NE, 3, 4); } else if (o->shape == Shape_cell16){ cells = NEW(REF ARRAY OF ARRAY OF uint_vec_t , g.NE, 4, 4); } else if (o->shape == Shape_cell24){ cells = NEW(REF ARRAY OF ARRAY OF uint_vec_t , g.NE, 3, 6); } /* computing the cells information */ for (i = 0; i < g.NE; i++) { VAR p: REF uint_vec_t; /* the tips of each @{edge->?} "e". */ k,l: uint = 0; { if (o->shape == Shape_cell5) { p = NEW(REF uint_vec_t ,3); } else if (o->shape == Shape_cell16){ p = NEW(REF uint_vec_t ,4); } else if (o->shape == Shape_cell24){ p = NEW(REF uint_vec_t ,3); } ??? e = g.edge[i]; ??? O = e[0]; ??? d = e[1]; { for (j = 0; j < g.NF; j++) { ??? f = g.wall[j]; ??? a = f[0]; ??? b = f[1]; ??? c = f[2]; { if (( (O == a)) && (d == b)){ p[k] = c; k++; } else if ((O == a) && (d == c)){ p[k] = b; k++; } else if ((O == b) && (d == a)){ p[k] = c; k++; } else if ((O == b) && (d == c)){ p[k] = a; k++; } else if ((O == c) && (d == a)){ p[k] = b; k++; } else if ((O == c) && (d == b)){ p[k] = a; k++; } } } /* Create the cells */ if (o->shape == Shape_cell5) { for (m = 0; m < 3; m++) { e1 = NEW(REF ARRAY OF INTEGER,4); e1[0] = O; e1[1] = d; e1[2] = p[m]; e1[3] = p[(m+1) % 3]; cells[i][m][0] = e1[0]; cells[i][m][1] = e1[1]; cells[i][m][2] = e1[2]; cells[i][m][3] = e1[3]; if (o->detail) { PrintRow4I(cells[i][l]); } } } else if (o->shape == Shape_cell16){ ??? ext = CorretAttribution(p); { for (j = 0; j < 4; j++) { cells[i][l][0] = O; cells[i][l][1] = d; cells[i][l][2] = ext[j][0]; cells[i][l][3] = ext[j][1]; if (o->detail) { PrintRow4I(cells[i][l]); } l++; } } } else if (o->shape == Shape_cell24){ for (m = 0; m < 3; m++) { e1 = NEW(REF ARRAY OF INTEGER,4); e1[0] = O; e1[1] = d; e1[2] = p[m]; e1[3] = p[(m+1) % 3]; cells[i][m][0] = e1[0]; cells[i][m][1] = e1[1]; cells[i][m][2] = e1[2]; cells[i][m][3] = e1[3]; cells[i][m][4] = ComputeTips(cells[i][m][0],cells[i][m][2], cells[i][m][3],cells[i][m][1]); cells[i][m][5] = ComputeTips(cells[i][m][1],cells[i][m][2], cells[i][m][3],cells[i][m][0]); assert(! AreAdjacents(cells[i][m][2],cells[i][m][3])); assert(! AreAdjacents(cells[i][m][4],cells[i][m][1])); assert(! AreAdjacents(cells[i][m][5],cells[i][m][0])); assert( AreAdjacents(cells[i][m][4],cells[i][m][5])); } } } } } if (o->shape == Shape_cell5) { for (i = 0; i < g.NE; i++) { for (j = 0; j < 3; j++) { if ((! Present4(cells[i][j]))) { Save4(cells[i][j]); } } }; } else if (o->shape == Shape_cell16){ for (i = 0; i < g.NE; i++) { for (j = 0; j < 4; j++) { if ((! Present4(cells[i][j]))) { Save4(cells[i][j]) } } }; } else if (o->shape == Shape_cell24){ for (i = 0; i < g.NE; i++) { for (j = 0; j < 3; j++) { if ((! Present6(cells[i][j]))) { Save6(cells[i][j]); } } } } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { cell4[i][j] = Stack4[i][j]; } } } else if (o->shape == Shape_cell24){ for (i = 0; i < cellnum; i++) { for (j = 0; j < 6; j++) { cell6[i][j] = Stack6[i][j]; } } } if (o->detail) { fprintf(stderr, o->shapeName & "\n"); fprintf(stderr, "cells " & Fmt.Int(cellnum) & "\n"); for (i = 0; i < cellnum; i++) { fprintf(stderr, Fmt.Pad(Fmt.Int(i),3) & ": "); if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (j = 0; j < 4; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(cell4[i][j]), 5) & " "); } fprintf(stderr, "\n"); } else if (o->shape == Shape_cell24){ for (j = 0; j < 6; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(cell6[i][j]), 5) & " "); } fprintf(stderr, "\n"); } } } void SetCornersTetra(uint Ti, z4_t row) /* Set the labels "row" in the tetrahedron Ti. */ { Node_t a = OrgV(tetra[Ti].p[0]); Node_t b = OrgV(Clock(tetra[Ti].p[0])); Node_t c = OrgV(PrevE(tetra[Ti].p[1])); Node_t d = OrgV(PrevE(tetra[Ti].p[0])) { a->num = row[0]; b->num = row[1]; c->num = row[2]; d->num = row[3]; } } SetCornersTetra; /* UNUSED */ bool_t Same4(a,b: z4_t) /* Decides if the arrays "a" and "b" are the same without consider the order between then. */ { ??? a0 = a[0]; ??? a1 = a[1]; ??? a2 = a[2]; ??? a3 = a[3]; ??? b0 = b[0]; ??? b1 = b[1]; ??? b2 = b[2]; ??? b3 = b[3]; { if (((a0 == b0) && (a1 == b1) && (a2 == b2) && (a3 == b3))) { return TRUE; } return FALSE; } } Same4; void DrawTetra(uint Ti, z4_t row) /* Draw the tetrahedron "Ti" with the labels "row". */ <* FATAL OSError.E); { ??? File = Fmt.Int(Ti); ??? wr = FileWr.Open("Tetrahedron-" & File & ".inc"); frgb_t color = (frgb_t){0.0,0.0,0.0}; double transp = 0.0; ?? x = (r3_t){0.0,0.0,0.0}; ?? y = (r3_t){0.0,-0.7071,-0.7071}; ?? z = (r3_t){-0.7071,-0.7071,0.0}; ?? w = (r3_t){-0.7071,0.0,-0.7071}; { fprintf(wr, "// Include File: \n"); WritePOVCylinder(wr,x,y,0.004,color,transp,TRUE); WritePOVCylinder(wr,x,z,0.004,color,transp,TRUE); WritePOVCylinder(wr,x,w,0.004,color,transp,TRUE); WritePOVCylinder(wr,y,z,0.004,color,transp,TRUE); WritePOVCylinder(wr,y,w,0.004,color,transp,TRUE); WritePOVCylinder(wr,z,w,0.004,color,transp,TRUE); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[0]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.085\n"); fprintf(wr, " translate <-0.025,-0.12500,-1.0000>\n"); fprintf(wr, " translate 0.275*x\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[1]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.125\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.550000,-0.0000,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[3]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.085\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.1350000,-0.6500,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[2]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.095\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.2750000,-0.5000,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(Ti) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.1250000,-0.25000,-1.0000>\n"); fprintf(wr, " }\n"); fclose(wr); } } DrawTetra; void DrawOcta(Ouint i; row: Row6I) /* Draw the octahedron "Oi" with the labels "row". */ <* FATAL OSError.E); { ??? File = Fmt.Int(Oi); ??? wr = FileWr.Open("Octahedron-" & File & ".inc"); frgb_t color == (frgb_t){0.0,0.0,0.0}; double transp = 0.0; ??? x = (r3_t){-0.4367, 0.3938, 0.8087}; ??? y = (r3_t){ 0.6782, 0.7325, 0.0134}; ??? z = (r3_t){-0.5818, 0.5558,-0.5931}; ??? w = (r3_t){ 0.5882,-0.5574, 0.5852}; ??? r = (r3_t){-0.6862,-0.7250,-0.0091}; ??? s = (r3_t){ 0.4383,-0.3997,-0.8051}; { fprintf(wr, "// Include File: \n"); WritePOVCylinder(wr,x,y,0.008,color,transp,TRUE); WritePOVCylinder(wr,x,z,0.008,color,transp,TRUE); WritePOVCylinder(wr,y,z,0.008,color,transp,TRUE); WritePOVCylinder(wr,x,w,0.008,color,transp,TRUE); WritePOVCylinder(wr,y,w,0.008,color,transp,TRUE); WritePOVCylinder(wr,r,z,0.008,color,transp,TRUE); WritePOVCylinder(wr,x,r,0.008,color,transp,TRUE); WritePOVCylinder(wr,r,w,0.008,color,transp,TRUE); WritePOVCylinder(wr,s,r,0.008,color,transp,TRUE); WritePOVCylinder(wr,z,s,0.008,color,transp,TRUE); WritePOVCylinder(wr,s,y,0.008,color,transp,TRUE); WritePOVCylinder(wr,w,s,0.008,color,transp,TRUE); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[0]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.4367,0.3938,0.8087>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[1]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.6782,0.7325,0.0134>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[3]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.5818,0.5558,-0.5931>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[2]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.6862,-0.7250,-0.0091>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[4]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.5882,-0.5574,0.5852>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[5]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.2750000,-0.5000,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(Oi) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.4383,-0.3997,-0.8051>\n"); fprintf(wr, " }\n"); fclose(wr); } } DrawOcta; void SetCornersOcta(Ouint i; row: Row6I) /* Set the labels "row" in the octahedron Oi. */ { Node_t a = OrgV(octa[Oi,0]); Node_t b = OrgV(octa[Oi,7]); Node_t c = OrgV(PrevE(octa[Oi,7])); Node_t d = OrgV(PrevE(octa[Oi,0])); Node_t e = OrgV(octa[Oi,1]); Node_t f = OrgV(Clock(octa[Oi,1])) { a->num = row[0]; b->num = row[1]; c->num = row[2]; d->num = row[3]; e->num = row[4]; f->num = row[5]; } } SetCornersOcta; bool_t MustBeGlued(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have coherent orientations and must be glued. */ { Node_t a = OrgV(Ti)->num; Node_t ae = OrgV(NextE(Ti))->num; ??? ae_1 = OrgV(PrevE(Ti))->num; Node_t b = OrgV(Tj)->num; Node_t be = OrgV(NextE(Tj))->num; ??? be_1 = OrgV(PrevE(Tj))->num; { if (((a == b) && (ae == be) && (ae_1 == be_1) OR (a == b) && (ae == be_1) && (ae_1 == be))){ return TRUE; } return FALSE } } MustBeGlued; bool_t BadAttribution(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have incoherent orientations. */ { Node_t i0 = OrgV(Ti)->num; ??? i1 = OrgV(NextE(Ti))->num; ??? i2 = OrgV(PrevE(Ti))->num; Node_t j0 = OrgV(Tj)->num; ??? j1 = OrgV(NextE(Tj))->num; ??? j2 = OrgV(PrevE(Tj))->num; { if ((SpinBit(Ti)!=SpinBit(Tj))) { if (((i0 == j0) && (i1 == j2) && (i2 == j1) OR (i0 == j2) && (i1 == j1) && (i2 == j0) OR (i0 == j1) && (i1 == j0) && (i2 == j2) )){ return TRUE; } } if ((SpinBit(Ti) == SpinBit(Tj))) { if (((i0 == j0) && (i1 == j1) && (i2 == j2) OR (i0 == j2) && (i0 == j0) && (i2 == j1) OR (i0 == j1) && (i1 == j2) && (i2 == j0) )){ return TRUE; } } return FALSE } } BadAttribution; void PrintCorners(Tuint i) /* Print the corners of the triangular wall "Ti". */ { Node_t a = OrgV(walls[Ti])->num; Node_t ae = OrgV(NextE(walls[Ti]))->num; ??? ae_1 = OrgV(PrevE(walls[Ti]))->num; { fprintf(stderr, Fmt.Pad(Fmt.Int(a),3) & " " \ Fmt.Pad(Fmt.Int(ae),3) \ " " & Fmt.Pad(Fmt.Int(ae_1),3) & " "); } } PrintCorners; REF ARRAY OF EightPlaces_t poly ; id : uint = 0; count : uint = 1; walls : REF Place_vec_t; glues : REF ARRAY OF z4_t; c = NEW(REF Triangulation.Coords_t, 48); void SetCoorOcta(Ouint i; row: Row6I) /* Set the coord "row" in the octahedron Oi. */ void SetCoords(Place_t e, r4_t *cv) /* set the origin node od the @place "e" with "cv". */ { c[OrgV(e)->num] = cv; } SetCoords; r4_t BaryOcta() /* Return the barycenter of the octahedron.*/ r4_t b = (r4_t){0.0, ..}; { for (i = 0; i < 6; i++) { b = r4_Add(b, g.c[row[i]]); } return r4_Scale(1.0/6.0, b); } BaryOcta; { SetCoords(octa[Oi,0], g.c[row[0]]); SetCoords(octa[Oi,7], g.c[row[1]]); SetCoords(PrevE(octa[Oi,7]),g.c[row[2]]); SetCoords(PrevE(octa[Oi,0]),g.c[row[3]]); SetCoords(octa[Oi,1], g.c[row[4]]); SetCoords(Clock(octa[Oi,1]), g.c[row[5]]); SetCoords(PrevE(PrevF(octa[Oi,4])), BaryOcta()); Mis.WritePoint(stderr, BaryOcta()); fprintf(stderr,"\n"); } SetCoorOcta; { poly = NEW(REF ARRAY OF EightPlaces_t,cellnum); tetra = NEW(REF ARRAY OF ARRAY [0..3] OF Place_t,cellnum); octa = NEW(REF ARRAY OF EightPlaces_t,cellnum); if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { Place_vec_t walls = Place_vec_new( 4*cellnum); glues = NEW(REF ARRAY OF z4_t, 2*cellnum); /* Create topological tetrahedra */ for (i = 0; i < cellnum; i++) { poly[i] = MakeTetraTopo(1,1); } /* Create the tetrahedra */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { tetra[i].p[j] = poly[i,j]; assert(Ppos(tetra[i].p[j]) == NULL); } } } else if (o->shape == Shape_cell24){ Place_vec_t walls = Place_vec_new( 8*cellnum); glues = NEW(REF ARRAY OF z4_t, 4*cellnum); /* Create the octahedra */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 8; j++) { octa[i] = Squared.MakeOctahedronTriang(TRUE); assert(Ppos(octa[i,j]) == NULL); } } } /* cells with corners perfectly assigments */ if (o->shape == Shape_cell5) { cell4[0] = (z4_t){{2,3,4,1}}; cell4[1] = (z4_t){{2,3,1,0}}; cell4[2] = (z4_t){{2,3,0,4}}; cell4[3] = (z4_t){{3,4,1,0}}; cell4[4] = (z4_t){{4,2,1,0}}; } else if (o->shape == Shape_cell16){ cell4[0] = (z4_t){{5,6,7,4}}; cell4[1] = (z4_t){{5,6,4,3}}; cell4[2] = (z4_t){{5,6,3,0}}; cell4[3] = (z4_t){{5,6,0,7}}; cell4[4] = (z4_t){{6,7,4,1}}; cell4[5] = (z4_t){{6,7,1,0}}; cell4[6] = (z4_t){{7,5,4,2}}; cell4[7] = (z4_t){{7,5,2,0}}; cell4[8] = (z4_t){{4,6,1,3}}; cell4[9] = (z4_t){{7,4,1,2}}; cell4[10] = (z4_t){{4,5,3,2}}; cell4[11] = (z4_t){{0,6,3,1}}; cell4[12] = (z4_t){{7,0,2,1}}; cell4[13] = (z4_t){{0,5,2,3}}; cell4[14] = (z4_t){{1,4,3,2}}; cell4[15] = (z4_t){{0,1,3,2}}; } else if (o->shape == Shape_cell24){ cell6[0] = Row6I{ 0, 8, 9,10,11, 1}; cell6[1] = Row6I{ 0, 8,10,12,14, 3}; cell6[2] = Row6I{ 0, 8,12, 9,13, 2}; cell6[3] = Row6I{ 8, 9, 1, 2,16,17}; cell6[4] = Row6I{ 9, 0,11,13, 7,15}; cell6[5] = Row6I{10, 8, 1, 3,18,16}; cell6[6] = Row6I{ 0,10,11,14,15, 6}; cell6[7] = Row6I{ 1, 9,11,17,19, 7}; cell6[8] = Row6I{10, 1,11,18, 6,19}; cell6[9] = Row6I{ 8,12, 2, 3,16,20}; cell6[10] = Row6I{12, 0,13,14, 5,15}; cell6[11] = Row6I{ 9, 2,13,17, 7,21}; cell6[12] = Row6I{ 2,12,13,20,21, 5}; cell6[13] = Row6I{ 3,10,14,18,22, 6}; cell6[14] = Row6I{12, 3,14,20, 5,22}; cell6[15] = Row6I{ 1,16,17,18,19, 4}; cell6[16] = Row6I{16, 2,17,20, 4,21}; cell6[17] = Row6I{ 3,16,18,20,22, 4}; cell6[18] = Row6I{14,15, 5, 6,22,23}; cell6[19] = Row6I{15,13, 5, 7,23,21}; cell6[20] = Row6I{11,15, 6, 7,19,23}; cell6[21] = Row6I{18,19, 6, 4,22,23}; cell6[22] = Row6I{17, 7,19,21, 4,23}; cell6[23] = Row6I{ 5,23,21,22,20, 4}; }; if (o->draw) { if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (i = 0; i < cellnum; i++) { fprintf(stderr, "Drawing tetrahedron :" & Fmt.Int(i) & "\n"); DrawTetra(i,cell4[i]); } } else if (o->shape == Shape_cell24){ for (i = 0; i < cellnum; i++) { fprintf(stderr,"Drawing octahedron :"&Fmt.Int(i) & "\n"); DrawOcta(i,cell6[i]); } } }; if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { /* set the labels for each tetrahedra */ for (i = 0; i < cellnum; i++) { SetCornersTetra(i,cell4[i]); } } else if (o->shape == Shape_cell24){ /* set the labels for each octahedra */ for (i = 0; i < cellnum; i++) { SetCornersOcta(i,cell6[i]); } if (o->fixed) { for (i = 0; i < cellnum; i++) { SetCoorOcta(i,cell6[i]); } } }; /* builds the table of walls for choose which tetrahedra must be gluing. */ if (o->detail) { fprintf(stderr, "C id table wall\n"); fprintf(stderr, "-------------------------\n"); }; for (i = 0; i < cellnum; i++) { if (o->detail) { fprintf(stderr, Fmt.Int(i) & "\n"); } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (k = 0; k < 4; k++) { walls[(4*i)+k] = tetra[i].p[k]; if (o->detail) { fprintf(stderr," "& Fmt.Pad(Fmt.Int(id),4)&" "); id++; PrintCorners((4*i)+k); fprintf(stderr, " " & Fmt.Int(k) & "\n"); } } } else if (o->shape == Shape_cell24){ for (k = 0; k < 8; k++) { walls[(8*i)+k] = octa[i,k]; if (o->detail) { fprintf(stderr," "&Fmt.Pad(Fmt.Int(id),4)& " "); id++; PrintCorners((8*i)+k); fprintf(stderr, " " & Fmt.Int(k) & "\n"); } } } } /* computing which cells must be gluing. */ for(k = 0; k < walls.ne; k++) { for (l = k+1 TO LAST(walls^)) { for (m = 0; m < 3; m++) { ??? e = NextEK(walls[l], m); { if ((MustBeGlued(walls[k],e))) { if (o->detail) { fprintf(stderr, Fmt.Int(count) & "\n"); fprintf(stderr, "must be gluing: walls[" & Fmt.Int(k) \ "] with "); fprintf(stderr, "walls[" & Fmt.Int(l) &"]\n"); } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { ??? kc = k % 4; ??? kt = k DIV 4; ??? lc = l % 4; ??? lt = l DIV 4; { if (o->detail) { fprintf(stderr, " tetra["&Fmt.Int(kt) & "," \ Fmt.Int(kc) & "] and tetra[" & Fmt.Int(lt) & "," \ Fmt.Int(lc) & "]\n\n"); } glues[count-1] = (z4_t){{kt,lt,kc,lc}}; count++; if ((BadAttribution(walls[k],e))) { fprintf(stderr, "Bad Attribution " & " tetra["& Fmt.Int(kt) &"and tetra[" & Fmt.Int(lt) & "]\n"); } } } else if (o->shape == Shape_cell24){ ??? kc = k % 8; ??? kt = k DIV 8; ??? lc = l % 8; ??? lt = l DIV 8; { if (o->detail) { fprintf(stderr, " octa["&Fmt.Int(kt) & "," \ Fmt.Int(kc) & "] and octa[" & Fmt.Int(lt) & "," \ Fmt.Int(lc) & "]\n\n"); } glues[count-1] = (z4_t){{kt,lt,kc,lc}}; } count++; } } } } } } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { /* Do the automatic gluing of tetrahedra */ for (i = 0; i < 2*cellnum; i++) { ??? c = glues[i]; { EVAL GlueTetras(c[0],c[1],c[2],c[3]); } } } else if (o->shape == Shape_cell24){ /* Gluing the triangulated octahedra. */ /* 1-5 */ Glue(Spin(PrevE(octa[0,0])), octa[6,7], 1); Glue(Spin(NextE(octa[0,1])), octa[8,7], 1); Glue(Spin(NextE(octa[0,2])), octa[5,7], 1); Glue(Spin(octa[0,3]), octa[1,7], 1); Glue(Clock(PrevE(octa[0,4])), octa[4,7], 1); /* 6-10 */ Glue(Clock(NextE(octa[0,5])), octa[7,7], 1); Glue(Clock(NextE(octa[0,6])), octa[3,7], 1); Glue(Spin(octa[0,7]), octa[2,3], 1); Glue(Clock(PrevE(octa[1,0])), octa[10,3],1); Glue(Spin(NextE(octa[1,1])), octa[14,7],1); /* 10-15 */ Glue(Clock(NextE(octa[1,2])), octa[9,3], 1); Glue(Spin(octa[1,3]), octa[2,7], 1); Glue(Spin(PrevE(octa[1,4])), octa[6,3], 1); Glue(Clock(NextE(octa[1,5])), octa[13,7],1); Glue(Spin(NextE(octa[1,6])), octa[5,3], 1); /* 16-20 */ Glue(Clock(PrevE(octa[2,0])), octa[4,3], 1); Glue(Spin(NextE(octa[2,1])), octa[11,7],1); Glue(Clock(NextE(octa[2,2])), octa[3,3], 1); Glue(Clock(PrevE(octa[2,4])), octa[10,7],1); Glue(Clock(NextE(octa[2,5])), octa[12,7],1); /* 21- 25 */ Glue(Clock(NextE(octa[2,6])), octa[9,7], 1); Glue(Spin(octa[3,0]), octa[9,4], 1); Glue(Spin(PrevE(octa[3,1])), octa[16,7],1); Glue(Clock(NextE(octa[3,2])), octa[11,3],1); Glue(Clock(octa[3,4]), octa[5,6], 1); /* 26-30 */ Glue(Clock(PrevE(octa[3,5])), octa[15,7],1); Glue(Spin(NextE(octa[3,6])), octa[7,3], 1); Glue(Spin(octa[4,0]), octa[11,4],1); Glue(Clock(NextE(octa[4,1])), octa[19,3],1); Glue(Spin(octa[4,2]), octa[10,6],1); /* 31-35 */ Glue(Clock(octa[4,4]), octa[7,6], 1); Glue(Spin(NextE(octa[4,5])), octa[20,3],1); Glue(Clock(octa[4,6]), octa[6,4], 1); Glue(Clock(PrevE(octa[5,0])), octa[13,3],1); Glue(Spin(NextE(octa[5,1])), octa[17,7],1); /* 36-39 */ Glue(Clock(octa[5,2]), octa[9,0], 1); Glue(Spin(PrevE(octa[5,4])), octa[8,3], 1); Glue(Spin(NextE(octa[5,5])), octa[15,3],1); Glue(Clock(octa[6,0]), octa[10,2],1); /* 40-44 */ Glue(Clock(PrevE(octa[6,1])), octa[18,3],1); Glue(Spin(octa[6,2]), octa[13,6],1); Glue(Clock(PrevE(octa[6,5])), octa[20,7],1); Glue(Clock(octa[6,6]), octa[8,4], 1); Glue(Spin(octa[7,0]), octa[15,4],1); /* 45-50 */ Glue(Spin(NextE(octa[7,1])), octa[22,7],1); Glue(Clock(octa[7,2]), octa[11,0],1); Glue(Clock(octa[7,4]), octa[8,6], 1); Glue(Spin(PrevE(octa[7,5])), octa[20,0],1); Glue(Clock(octa[8,0]), octa[13,2],1); /* 50-54 */ Glue(Spin(NextE(octa[8,1])), octa[21,7],1); Glue(Clock(octa[8,2]), octa[15,0],1); Glue(Clock(NextE(octa[8,5])), octa[20,4],1); Glue(Clock(PrevE(octa[9,1])), octa[17,3],1); Glue(Clock(NextE(octa[9,2])), octa[14,3],1); /* 55-60 */ Glue(Spin(PrevE(octa[9,5])), octa[16,3],1); Glue(Spin(NextE(octa[9,6])), octa[12,3],1); Glue(Spin(octa[10,0]), octa[14,4],1); Glue(Spin(NextE(octa[10,1])), octa[18,7],1); Glue(Clock(octa[10,4]), octa[12,6],1); Glue(Clock(NextE(octa[10,5])), octa[19,7],1); /* 61-65 */ Glue(Clock(PrevE(octa[11,1])),octa[22,3],1); Glue(Spin(octa[11,2]), octa[16,6],1); Glue(Spin(NextE(octa[11,5])), octa[19,2],1); Glue(Clock(octa[11,6]), octa[12,4],1); Glue(Clock(octa[12,0]), octa[16,2],1); /* 66-71 */ Glue(Spin(NextE(octa[12,1])), octa[23,4],1); Glue(Clock(octa[12,2]), octa[14,0],1); Glue(Clock(PrevE(octa[12,5])),octa[19,6],1); Glue(Spin(octa[13,0]), octa[17,4],1); Glue(Spin(PrevE(octa[13,1])), octa[21,4],1); Glue(Clock(octa[13,4]), octa[14,6],1); /* 72-77 */ Glue(Spin(PrevE(octa[13,5])), octa[18,0],1); Glue(Clock(PrevE(octa[14,1])),octa[23,0],1); Glue(Clock(octa[14,2]), octa[17,0],1); Glue(Clock(NextE(octa[14,5])), octa[18,4],1); Glue(Clock(PrevE(octa[15,1])),octa[21,3],1); Glue(Spin(octa[15,2]), octa[17,6],1); /* 78-82 */ Glue(Clock(NextE(octa[15,5])), octa[22,4],1); Glue(Clock(octa[15,6]), octa[16,4],1); Glue(Clock(octa[16,0]), octa[17,2],1); Glue(Spin(PrevE(octa[16,1])), octa[23,5],1); Glue(Spin(PrevE(octa[16,5])), octa[22,0],1); /* 83-88 */ Glue(Clock(NextE(octa[17,1])), octa[23,1],1); Glue(Spin(PrevE(octa[17,5])), octa[21,0],1); Glue(Spin(octa[18,1]), octa[21,5],1); Glue(Spin(octa[18,2]), octa[20,6],1); Glue(Spin(NextE(octa[18,5])), octa[23,3],1); Glue(Clock(octa[18,6]), octa[19,4],1); /* 89-93 */ Glue(Clock(octa[19,0]), octa[20,2],1); Glue(Clock(PrevE(octa[19,1])),octa[22,2],1); Glue(Clock(PrevE(octa[19,5])),octa[23,7],1); Glue(Spin(NextE(octa[20,1])), octa[22,6],1); Glue(Clock(octa[20,5]), octa[21,6],1); /* 94-96 */ Glue(Clock(NextE(octa[21,1])), octa[23,2],1); Glue(Spin(PrevE(octa[21,2])), octa[22,5],1); Glue(Spin(octa[22,1]), octa[23,6],1); } /* Builds and writes the topology. */ fprintf(stderr, "Building the topology of " & o->shapeName & ":\n"); if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { ??? a = tetra[1].p[1]; ??? top = MakeElemTable(a,0); Coords_t c = GenCoords(&top);; { /* seting the elements root for edges and walls.*/ for (i = 0; i < top.wall.ne; i++) { ??? f = top.wall[i]; { f->root = f->num; } } for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i]; { e->root = e->num; } } WriteTopology(o->shapeName, top, "Created by AutoGluing: " & o->shapeName & ".tp on " \ Today()); WriteTable(o->shapeName, top, "Created by AutoGluing: " & o->shapeName & ".tb on " \ Today()); WriteMaterials(o->shapeName, top, "Created by AutoGluing: " & o->shapeName& ".ma on " \ Today()); WriteState(o->shapeName, top, c, "Created by AutoGluing: " & o->shapeName & ".st on " \ Today() &"\nRandom Geometry"); } } else if (o->shape == Shape_cell24){ ??? a = octa[21,1]; ??? top = MakeElemTable(a,0); ??? ca = GenCoords(top)^; { /* seting the elements root for edges and walls.*/ for (i = 0; i < top.wall.ne; i++) { ??? f = top.wall[i]; { f->root = f->num; f->exists = TRUE; } } for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i]; { e->root = e->num; e->exists = TRUE; } } WriteTopology(o->shapeName, top, "Created by AutoGluing: " & o->shapeName & ".tp on " \ Today()); WriteMaterials(o->shapeName, top, "Created by AutoGluing: " & o->shapeName& ".ma on " \ Today()); if (! o->fixed) { WriteState(o->shapeName, top, ca, "Created by AutoGluing: " & o->shapeName & ".st on " \ Today() &"\nRandom Geometry"); } else if ( o->fixed){ WriteState(o->shapeName, top, c^, "Created by AutoGluing: " & o->shapeName & ".st on " \ Today() &"\nFixed Geometry"); } } } } } } } DoIt; /* Procedures for stacking */ bool_t Present4(array : z4_t) /* Return TRUE if "array" its on the stack, FALSE c.c. */ uint nstack = cellnum; e1 : REF uint_vec_t; st : REF uint_vec_t; { e1 = NEW(REF uint_vec_t ,4); st = NEW(REF uint_vec_t ,4); for (i = 0; i < 4; i++) { e1[i] = array[i]; } Mis.Sort(3,e1); while (nstack > 0) { nstack--; for (i = 0; i < 4; i++) { st[i] = Stack4[nstack][i]; } Mis.Sort(3,st); if (st^ == e1^){ return TRUE; } } return FALSE; } Present4; void Save4(VAR array : z4_t) /* Saves the array "array" on the stack "Stack4". */ { Stack4[cellnum] = array; cellnum = cellnum + 1; } /* END Save4 */ bool_t Present6(array : Row6I) /* Return TRUE if "array" its on the stack "Stack6", FALSE c.c. */ uint nstack = cellnum; e1 : REF uint_vec_t; st : REF uint_vec_t; { e1 = NEW(REF uint_vec_t ,6); st = NEW(REF uint_vec_t ,6); for (i = 0; i < 6; i++) { e1[i] = array[i]; } Mis.Sort(5,e1); while (nstack > 0) { nstack--; for (i = 0; i < 6; i++) { st[i] = Stack6[nstack][i]; } Mis.Sort(5,st); if (st^ == e1^){ return TRUE; } } return FALSE; } Present6; void Save6(VAR array : Row6I) /* Saves the array "array" on the stack "Stack6". */ { Stack6[cellnum] = array; cellnum = cellnum + 1; } /* END Save6 */ /* UNUSED */ bool_t Present(card : CARDI) /* Return TRUE if "card" its on the stack "STACK", FALSE c.c. */ uint nstack = tpst; { while (nstack > 0){ nstack = nstack-1; if (Stack.El[nstack] == card){ return TRUE; } } return FALSE; } Present; /* UNUSED */ void Save(card : CARDI) /* Saves the cardinal value "card" on the stack "Stack". */ { Stack.El[tpst] = card; tpst = tpst + 1; } /* END Save */ /* Procedures for printing */ void PrintRow4I(m: z4_t) /* Print an array of four integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & " " \ Fmt.Int(m[2]) & " " & Fmt.Int(m[3]) & "\n"); } /* END PrintRow4I */ /* UNUSED */ void PrintRow6I(m: Row6I) /* Print an array of six integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & " " \ Fmt.Int(m[2]) & " " & Fmt.Int(m[3]) & " " & Fmt.Int(m[4]) \ " " & Fmt.Int(m[5]) & "\n"); } /* END PrintRow6I */ /* UNUSED */ void PrintRow2I(m: Row2I) /* Print an array of two integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & "\n"); } /* END PrintRow2I */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "5cell"))) { o->shape = Shape_cell5 } else if (0 == strcmp(o->shapeName, "16cell"))){ o->shape = Shape_cell16 } else if (0 == strcmp(o->shapeName, "24cell"))){ o->shape = Shape_cell24 } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n"); } o->draw = argparser_keyword_present(pp, "-draw"); o->detail = argparser_keyword_present(pp, "-detail"); o->fixed = argparser_keyword_present(pp, "-fixed"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: AutoGluing \\\n" \ " -shape { 5cell | 16cell | 24cell }\\\n" \ " [ -draw ] [ -detail ] [ -fixed ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } AutoGluing. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/BarySubdivision.c #define PROG_NAME "BarySubdivision" #define PROG_DESC "???" #define PROG_VERS "1.0" #define BarySubdivision_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program builds the "barycentric subdivision" of one topology (".tp" file) of any given 3D map (without boundary or with boundary). In the case of maps with boundary, this program only considers 3D maps with Degree Ring Wall (top->drf) equal to two. So, the compute of a second bary- center subdivision for this case isn't contemplating. . Added the option "net" for simulate textures on existing walls with thin cylinders and small spheres. */ #include // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // #INCLUDE #include CONST double order = 2; mid == 1; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ bool_t fixed; /* Retains the previous geometry */ bool_t net; /* Implements the net walls */ } void DoIt() REF Place_vec_t ps ; nvv,nve,nvf,nvp: uint =0; /* number of node of types "VV","VE","VF"*/ /* and "VP" in the new topology. */ { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFile); ??? c = rc^; ??? NFE = top->wall.nelE; ??? vlt = "VP"; ??? vlf = "VF"; { Place_vec_t ps = Place_vec_new(NFE); fprintf(stderr, "Subdividing from: " & o->inFile & ".tp\n"); for (i = 0; i < NFE; i++) { ??? aposp = PposP(top->wedge[i]); ??? apneg = PnegP(top->wedge[i]; { if ((aposp != NULL) && (apneg #NULL)) { /* Make one Topological tetrahedron of 2x2 order, for each wedge in the topology and set the atributes "ca" for each original wedge. */ ps[i] = Bary.MakeWedge(order,order); ??? fes = NARROW(PWedge(ps[i]), Bary.wedge); double fet = PWedge(top->wedge[i]); ??? fn = fet.wall->num; ??? en = fet.edge->num; Node_t on = OrgV(top->wedge[i]); Node_t dn = OrgV(Clock(top->wedge[i])); ??? ovr = on.radius; ??? ovc = on.color; ??? ovt = on.transp; ??? ovl = on.label; ??? ove = on->exists; ??? dvr = dn.radius; ??? dvc = dn.color; ??? dvt = dn.transp; ??? dvl = dn.label; ??? dve = dn->exists; ??? era = top->edge[en].radius; ??? eco = top->edge[en].color; ??? eta = top->edge[en].transp; ??? eex = top->edge[en]->exists; ??? ero = top->edge[en]->root; ??? fco = top->wall[fn].color; ??? fta = top->wall[fn].transp; ??? fex = top->wall[fn]->exists; ??? fro = top->wall[fn]->root { assert(Octf.OrientationBit(top->wedge[i]) == 0); fet.ca = fes.ca; SetDual (fet.ca.e[3],vlt,vlf,FALSE,TRUE); SetPrimal(fet.ca.e[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,FALSE,TRUE,o->net); } } } } if ((! IsMapWithBorder(top))) { for (i = 0; i < NFE; i++) { ??? pa = top->wedge[i]; { GlueTetra(pa) } } /* Set the origins for all wedges in the triangulation */ ??? newtop = MakeElemTable(PWedge(top->wedge[NFE-1]).ca.e[1]); ??? nc = GenCoords(newtop)^; ??? com = "Subdivided from: " & o->inFile & ".tp\n" &"Created by Barycenter Subdivision: "&o->outFile \ ".tp on " & Today(); { for (i = 0; i < newtop.node.ne; i++) { ??? v = NARROW(newtop.node[i], Node); char *vl = v.label; { if (( Text.Equal(vl,"VV"))){ nvv++; } else if (0 == strcmp(vl,"VE"))){ nve++; } else if (0 == strcmp(vl,"VF"))){ nvf++; } else if (0 == strcmp(vl,"VP"))){ nvp++; } } } assert(newtop.node.ne == nvv + nve + nvf + nvp); assert(newtop.node.ne == top->node.ne + top->NE + top->wall.ne + top->cell.ne); assert(newtop.wall.ne == 8 * top->wall.nelE); assert(newtop.wedge.ne == 24 * top->wall.nelE); assert(newtop.cell.ne == 4 * top->wall.nelE); if (o->net) { /* we compute the number of existing walls in the previus topology. */ VAR nefp: uint = 0; /* existing walls in the previus topology */ neep: uint = 0; /* existing @{edge->?}s in the previus topology */ nevp: uint = 0; /* existing vert. in the previus topology */ neea: uint = 0; /* existing @{edge->?}s in the actual topology */ neva: uint = 0; /* existing vert. in the actual topology */ { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists){ nefp++;} } } for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { if (e->exists){ neep++; } } } for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { if (v->exists){ nevp++; } } } for (i = 0; i < newtop.edge.ne; i++) { ??? e = newtop.edge[i]; { if (e->exists){ neea++;} } } /*assert(neea == 2 * top->der * nefp + 2 * neep);*/ for (i = 0; i < newtop.node.ne; i++) { ??? v = newtop.node[i]; { if (v->exists){ neva++;} } } /*assert(neva == nevp + neep + nefp);*/ } } if (o->fixed) { /* compute new coordinates for nodes of type "VV" and "VE". */ for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Bary_Bary_Corner(a))->num; Node_t nv = OrgV(Bary_Bary_Corner(Clock(a)))->num; Node_t nx = OrgV(Clock(Bary_Bary_Corner(a)))->num; { nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); } } /* compute new coordinates for nodes of type "VF". */ for (j = 0; j < top->wall.ne; j++) { ??? a = top->wall[j].pa; Node_t uu = OrgV(Clock(Bary_Bary_Corner(Srot(a))));/* type VF */ ??? un = (Node_t)(uu); ??? ul = un.label; { assert0 == strcmp(ul,"VF")); nc[un->num] = Triangulation.WallBarycenter(a,c); } } /* compute new coordinates for nodes of type "VP". */ for (j = 0; j < top->cell.ne; j++) { ??? a = Srot(top->cell[j]); ??? p = Triangulation.MakeCellTopology(a); Place_t b = Tors(a); Node_t uu = OrgV(Bary_Bary_Corner(Srot(b))); ??? un = (Node_t)(uu); { r4_t ba = (r4_t){0.0,0.0,0.0,0.0}; VAR { for (k = 0; k < p.NV; k++) { ??? ver = p.vRef[k]; Node_t num = OrgV(ver)->num; { ba = r4_Add(ba,c[num]); } } nc[un->num] = r4_Scale(1.0/FLOAT(p.NV,double),ba); } } } } WriteTopology(o->outFile, newtop, com); if (! o->fixed) { WriteState(o->outFile, newtop, nc, com \ "\nRandom Geometry"); } else { WriteState(o->outFile, newtop, nc, com \ "\nFixed Geometry"); } WriteMaterials(o->outFile, newtop, com); /* unmark all the wedges */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); { fet.marks = FALSE; } } }; /***************************************************************** 3D maps with boundary ******************************************************************/ } else if ((IsMapWithBorder(top))){ for (i = 0; i < NFE; i++) { ps[i] = Bary.MakeWedge(mid,order); ??? fes = NARROW(PWedge(ps[i]),Bary.wedge); double fet = PWedge(top->wedge[i]); { fet.ca = fes.ca; } } /* Now, set the attributes for the a topological tetrahedron correspondly to the @place "a", and the tetrahedron correspondly to the adjacent @place "aFnext" */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); ??? fn = fet.wall->num; ??? en = fet.edge->num; Node_t on = OrgV(top->wedge[i]); Node_t dn = OrgV(Clock(top->wedge[i])); ??? ovr = on.radius; ??? ovc = on.color; ??? ovt = on.transp; ??? ovl = on.label; ??? ove = on->exists; ??? dvr = dn.radius; ??? dvc = dn.color; ??? dvt = dn.transp; ??? dvl = dn.label; ??? dve = dn->exists; ??? era = top->edge[en].radius; ??? eco = top->edge[en].color; ??? eta = top->edge[en].transp; ??? eex = top->edge[en]->exists; ??? ero = top->edge[en]->root; ??? fco = top->wall[fn].color; ??? fta = top->wall[fn].transp; ??? fex = top->wall[fn]->exists; ??? fro = top->wall[fn]->root; ??? pa = top->wedge[i]; Place_t paf = NextF(pa); Wedge_t fef = PWedge(NextF(pa)); { if ((! fet.marks) && ((PposP(pa) == PnegP(paf)))) { if ((PposP(pa)!=NULL)) { SetDual (fet.ca.e[3],vlt,vlf,TRUE,FALSE); SetPrimal(fet.ca.e[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,TRUE,FALSE,o->net); fet.marks = TRUE; } } if (! fef.marks) { SetDual (fet.ca.e[3],vlt,vlf,TRUE,TRUE); SetPrimal(fet.ca.e[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,TRUE,TRUE,o->net); fef.marks = TRUE; } } }; for (i = 0; i < NFE; i++) { ??? pa = top->wedge[i]; { GlueTetraBr(pa) } } ??? newtop = MakeElemTable(PWedge(top->wedge[NFE-1]).ca.e[1]); ??? nc = GenCoords(newtop)^; char *com = "Subdivided from: " & o->inFile & ".tp\n" &"Created by Barycenter Subdivision: "&o->outFile \ ".tp on " & Today(); { /* checks */ for (i = 0; i < newtop.node.ne; i++) { ??? v = NARROW(newtop.node[i], Node); double vl = v.label; { if (0 == strcmp(vl,"VV"))){ nvv++; } else if (0 == strcmp(vl,"VE"))){ nve++; } else if (0 == strcmp(vl,"VF"))){ nvf++; } else if (0 == strcmp(vl,"VP"))){ nvp++; } } } assert(newtop.node.ne == nvv + nve + nvf + nvp); assert(newtop.node.ne == top->node.ne + top->NE + top->wall.ne + top->cell.ne); if (o->fixed) { for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Bary_Bary_Corner(a))->num; Node_t nv = OrgV(Bary_Bary_Corner(Clock(a)))->num; Node_t nx = OrgV(Clock(Bary_Bary_Corner(a)))->num; Node_t u = OrgV(Bary_Bary_Corner(Srot(a))); ??? un = u->num; Node_t v = OrgV(Bary_Bary_Corner(Tors(a))); ??? vn = v->num; { nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); ??? u = (Node_t)(u); { double ul = u.label; double v = (Node_t)(v); double vl = v.label DO assert0 == strcmp(ul,"VF")); nc[un] = Triangulation.WallBarycenter(a,c); assert0 == strcmp(vl,"VP")); nc[vn] = Triangulation.Barycenter(top,c, TRUE); } } } } WriteTopology(o->outFile, newtop, com); if (! o->fixed) { WriteState(o->outFile, newtop, nc, com \ "\nRandom Geometry"); } else { WriteState(o->outFile, newtop, nc, com \ "\nFixed Geometry"); } WriteMaterials(o->outFile, newtop, com); /* unmark all the wedges, only for the case (top->bd==1) */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); { fet.marks = FALSE; } } } } return 0; } void GlueTetra(Place_t @p) /* Glues the topological tetrahedra such as the topology. */ { assert(PBits(a) == 0); Place_t b = NextF(a); Place_t c = PrevF(a); Place_t d = NextE(a); Place_t e = PrevE(a); { ??? aa = Bary_Corner(a); ??? bb = Bary_CCorner(b); { if (bb != aa) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(bb, aa, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(a, bb); Bary_SetCorner(Spin(Clock(a)), Bary_CCorner(Spin(Clock(b)))); } } ??? cc = Bary_Corner(c); ??? dd = Bary_CCorner(a); { if (dd != cc) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(dd, cc, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(c, dd); Bary_SetCorner(Spin(Clock(c)), Bary_CCorner(Spin(Clock(a)))); } } ??? ee = Bary_Corner(Srot(d)); ??? ff = Bary_CCorner(Srot(a)); { if (ff != ee) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(ff, ee, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(d), ff); Bary_SetCorner(Spin(Tors(d)), Bary_CCorner(Spin(Tors(a)))); } } ??? gg = Bary_Corner(Srot(a)); ??? hh = Bary_CCorner(Srot(e)); { if (gg != hh) { EVAL Triangulation.Glue(hh, gg, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(a), hh); Bary_SetCorner(Spin(Tors(a)), Bary_CCorner(Spin(Tors(e)))); } } } } /* END GlueTetra */ void GlueTetraBr(Place_t @p) /* Glueing the topological tetrahedra such as the topology. */ { assert(PBits(a) == 0); Place_t e = PrevE(a); Place_t b = NextF(a); { ??? gg = Bary_Corner(Srot(a)); ??? hh = Bary_CCorner(Srot(e)); { if ((a != e) && (gg != hh)) { EVAL Triangulation.Glue(hh, gg, mid, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(a), hh); Bary_SetCorner(Spin(Tors(a)), Bary_CCorner(Spin(Tors(e)))); } } ??? aa = Bary_Corner(a); ??? bb = Bary_CCorner(b); { if ((a#b) && (bb != aa) && ((PposP(a) == PnegP(NextF(a))))) { if ((PnegP(a)!=NULL)) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(bb, aa, order, TRUE); Bary_SetCorner(a,bb); Bary_SetCorner(Spin(Clock(a)), Bary_CCorner(Spin(Clock(b)))); } } } } } /* END GlueTetraBr */ void SetPrimal(Place_t @p, /* @place hanged on topological tetrahedron 2x2 or 1x2 */ REAL ovr; /* origen node radius */ ovc: frgb_t; /* origen node color */ ovt: frgb_t; /* origen node transparency */ char *ovl; /* origen node label */ bool_t ove; REAL dvr; /* destine node radius */ dvc: frgb_t; /* destine node color */ dvt: frgb_t; /* destine node transparency */ char *dvl; /* destine node label */ bool_t dve; REAL era; /* @{edge->?} radius */ eco: frgb_t; /* @{edge->?} color */ eta: frgb_t; /* @{edge->?} transparency */ bool_t eex; /* @{edge->?} exists */ INTEGER ero; /* @{edge->?} root */ fco: frgb_t; /* wall color */ fta: frgb_t; /* wall transparency */ bool_t fex; /* wall exists */ INTEGER fro; /* wall root */ bool_t mid; /* TRUE iff the topological tetrahedron is 1x2 */ bool_t side; /* indicate the side of the topological tetrahedron 1x2 */ bool_t net; /* simulates a grade with thin cylindres and spheres */ ) void SetNode( Node v; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL r; /* radius */ char *l; /* label */ ) { v->exists = e; v.color = c; v.transp = t; v.label = l; v.radius = r; } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) { t->exists = FALSE; } } SetGhostWall; void NewSetTriangle( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ INTEGER r; /* root */ ) { Wall_t f = PWall(b) { f->exists = e; f.color = c; f.transp = t; f->root = r; } } NewSetTriangle; void NewSetEdge( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL ra; /* radius */ INTEGER ro; /* root */ ) { ??? ee = NARROW(PEdge(b), @{Edge->?}); { ){ ee->exists = e; ee.color = c; ee.transp = t; ee.radius = ra; ee->root = ro; } } NewSetEdge; { /* set the origin of the @place ca.e[0] */ SetNode(Org(a), ove, ovc, ovt, ovr, ovl); /* set the origin of the @place Clock(ca.e[0]) */ SetNode(Org(Clock(a)), eex, eco, eta, era, "VE"); /* set the edge component of the topological tetrahedron */ NewSetEdge(a, eex, eco, eta, era, ero); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetNode(Org(Clock(b)), dve, dvc, dvt, dvr, dvl); NewSetEdge(b, eex, eco, eta, era, ero); } if (! mid) { SetGhostWall(a); SetGhostWall(NextF(a)); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); SetGhostWall(NextF(b)); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } if (net) { Edge_t X = PEdge(PrevE(PrevF(a))); Edge_t Y = PEdge(NextE(PrevF(a))); Place_t Z = Clock(PrevE(NextF(NextE(a)))); Edge_t W = PEdge(NextE(PrevF(Z))); Node_t S = OrgV(PrevE(PrevF(a))); ??? co = (frgb_t){1.00,1.000,0.500}, /* color, transparency and radius */ ??? tp = (frgb_t){0.00,0.000,0.000}, /* of the thin cylinder and sohere*/ double ra = 0.0025 { X->exists = TRUE; Y->exists = TRUE; W->exists = TRUE; S->exists = TRUE; X.color = co; X.radius = ra; X.transp = tp; Y.color = co; Y.radius = ra; Y.transp = tp; W.color = co; W.radius = ra; W.transp = tp; S.color = co; S.radius = ra; S.transp = tp; } } } else if (mid){ if (side) { SetGhostWall(a); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } } else { SetGhostWall(PrevF(a)); NewSetTriangle(a, fex, fco, fta, fro); Place_t an = Clock(PrevE(PrevF(NextE(PrevF(a))))); { SetGhostWall(an); NewSetTriangle(PrevF(an), fex, fco, fta, fro); } } } } /* END SetPrimal */ void SetDual(Place_t @p, char *vlt; char *vlf; bool_t mid; bool_t side; ) void SetNode(Node_t v; char *label) { ??? vv = (Node_t)(v); { ){ vv->exists = FALSE; vv.label = label; } } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) { t->exists = FALSE; } } SetGhostWall; PROCEDURE SetGhostEdge(Place_t @p) == { ??? t = NARROW(PEdge(a), @{Edge->?}); { t->exists = FALSE; } } SetGhostEdge; void SetRowedge(d: Place_t; r: uint) Place_t dn = d; VAR { if (r == 3) { for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } } dn = PrevF(dn); SetGhostEdge(NextE(dn)); SetGhostEdge(PrevE(dn)); } } else if (r == 2){ for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } dn = NextE(dn); } dn = PrevF(dn); SetGhostEdge(NextE(dn)); } } } SetRowedge; void SetRowTriangle(b: Place_t) { for (i = 0; i < 3; i++) { SetGhostWall(b); b = PrevF(b); } } SetRowTriangle; { if ((mid) && (side)){ SetNode(Org(a), vlf); SetNode(Org(Clock(a)), vlt); SetRowTriangle(a); SetRowedge(a,3); } else if ((mid) && (NOT side)){ SetNode(Org(a), vlt); SetNode(Org(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); } else if (! mid){ SetNode(Org(a), vlt); SetNode(Org(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); Place_t an = PrevE(NextF(NextE(a))); { SetNode(Org(an),vlt); SetRowTriangle(an); SetRowedge(Clock(an),2); } } } /* END SetDual */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->fixed = argparser_keyword_present(pp, "-fixed"); o->net = argparser_keyword_present(pp, "-net"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: BarySubdivision" \ " -inFile -outFile \\\n" \ " [ -fixed ] [ -net ] \n"); END¦ } } return o; } /* END GetOptions */ bool_t IsMapWithBorder(ElemTableRec_t *top) { for (i = 0; i < top->wall.nelE; i++){ ??? a = top->wedge[i]; ??? n = Pneg(a); ??? p = Ppos(a); { if ((n == NULL) && (p == NULL)){ return TRUE; }; } } return FALSE; } /* END IsMapWithBorder */ { DoIt() } BarySubdivision. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ Bary_Corner Bary_CCorner Bary_SetCorner // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/BezierToWire4.c #define PROG_NAME "BezierToWire4" #define PROG_DESC "???" #define PROG_VERS "1.0" #define BezierToWire4_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Writes cubic Bezier curves in the format expected by the "Wire4" - Interactive 4D Wireframe Display Program (".w4"). */ #define BezierToWire4_C_author \ "Modified by L.A.P.Lozada on 03-08-by lozada." // #INCLUDE #include #include // #INCLUDE #include #include #include TYPE double Row3I = ARRAY [0..2] OF INTEGER; typedef struct Options_t { char *outFile; From4: r4_t; To4: r4_t; Up4: r4_t; Over4: r4_t; Vangle4: double; From3: r3_t; To3: r3_t; Up3: r3_t; Vangle3: double; double FogDensity; INTEGER DepthCueLevels; cp0: r4_t; cp1: r4_t; cp2: r4_t; cp3: r4_t; } VAR uint ne; vcolor : Row3I = Row3I{100,100,100}; ecolor : Row3I = Row3I{0,255,255}; vradius : REAL = 1.0; eradius : REAL = 1.0; void WriteColor(FILE *wr, *c: Row3I) /* Write colors in RGB mode */ { Mis.WriteInt(wr,c[0]); fprintf(wr," "); Mis.WriteInt(wr,c[1]); fprintf(wr," "); Mis.WriteInt(wr,c[2]); } /* END WriteColor */ void DoIt() { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? cmt = "\n Make by SplineToWire4: " & o->outFile & ".w4 on " \ Today() & "\n"; { WriteWire4File(o, cmt); return 0; } void WriteWire4File(*o: Options_t; cmt: char *) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? w4 = FileWr.Open(o->outFile & ".w4"); { filefmt_write_comment(w4,cmt,'#'); fprintf(w4, "\n"); WriteWire4(o,w4); fclose(w4) } } /* END WriteWire4File */ void WriteWire4(*o: Options_t; w4: Wr.T) VAR { void WriteCoord(double x) { fprintf(w4, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 4), 7)); } WriteCoord; void WritePoint4D(*c: r4_t) { WriteCoord(c[0]); fprintf(w4, " "); WriteCoord(c[1]); fprintf(w4, " "); WriteCoord(c[2]); fprintf(w4, " "); WriteCoord(c[3]); } WritePoint4D; void WritePoint3D(*c: r3_t) { WriteCoord(c[0]); fprintf(w4, " "); WriteCoord(c[1]); fprintf(w4, " "); WriteCoord(c[2]); } WritePoint3D; { fprintf(w4, "DegreeRing@{Edge->?}s"); fprintf(w4," 0"); fprintf(w4,"\nDepthCueLevels ");Mis.WriteInt(w4,o->DepthCueLevels); fprintf(w4,"\nFogDensity "); Mis.WriteLong(w4, o->FogDensity); fprintf(w4,"\n"); fprintf(w4, "\nFrom4: "); WritePoint4D(o->From4); fprintf(w4, "\nTo4 : "); WritePoint4D(o->To4); fprintf(w4, "\nUp4 : "); WritePoint4D(o->Up4); fprintf(w4, "\nOver4: "); WritePoint4D(o->Over4); fprintf(w4, "\nVangle4: "); Mis.WriteLong(w4, o->Vangle4); fprintf(w4, "\n"); fprintf(w4, "\nFrom3: "); WritePoint3D(o->From3); fprintf(w4, "\nTo3 : "); WritePoint3D(o->To3); fprintf(w4, "\nUp3 : "); WritePoint3D(o->Up3); fprintf(w4, "\nVangle3: "); Mis.WriteLong(w4, o->Vangle3); fprintf(w4, "\n\nNodeList 105 :\n"); for (i = 0; i <= (99); i++) { ??? t = FLOAT(i, double)/99.0); ??? P = CubicBezier(t,o->cp0,o->cp1,o->cp2,o->cp3); { WritePoint4D(P); fprintf(w4, " : "); WriteColor(w4, vcolor); fprintf(w4, " : "); Mis.WriteRadius(w4, vradius); fprintf(w4, "\n"); ne++; } } /* reference axis */ fprintf(w4, " 0 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 1 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 1 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 1 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 0 1 : 255 255 255 : 0\n"); fprintf(w4, "\n"); fprintf(w4, "@{Edge->?}List " & Fmt.Int(ne+3) & ":\n"); for (i = 0; i < ne; i++) { if (i!=ne-1) { fprintf(w4, Fmt.Pad(Fmt.Int(i), 4) & " " \ Fmt.Pad(Fmt.Int(i+1),4)); fprintf(w4, " : "); /* color */ WriteColor(w4, ecolor); fprintf(w4, " : "); Mis.WriteRadius(w4, eradius); fprintf(w4, "\n"); } } fprintf(w4, " 100 101 : 125 125 125 : 1\n"); fprintf(w4, " 100 102 : 125 125 125 : 1\n"); fprintf(w4, " 100 103 : 125 125 125 : 1\n"); fprintf(w4, " 100 104 : 125 125 125 : 1\n"); fprintf(w4, "\nWallList 0\n"); fclose(w4); } } /* END WriteWire4 */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-cp0"); for (j = 0; j < 4; j++) { o->cp0[j] = pp.getNextLongReal(-100.0, 100.0); } argparser_get_keyword(pp, "-cp1"); for (j = 0; j < 4; j++) { o->cp1[j] = pp.getNextLongReal(-100.0, 100.0); } argparser_get_keyword(pp, "-cp2"); for (j = 0; j < 4; j++) { o->cp2[j] = pp.getNextLongReal(-100.0, 100.0); } argparser_get_keyword(pp, "-cp3"); for (j = 0; j < 4; j++) { o->cp3[j] = pp.getNextLongReal(-100.0, 100.0); } if ((argparser_keyword_present(pp, "-DepthCueLevels"))) { o->DepthCueLevels = argparser_get_next_int(pp, 1, 255); } else { o->DepthCueLevels = 16; } if ((argparser_keyword_present(pp, "-FogDensity"))) { o->FogDensity = pp.getNextLongReal(0.0, 1.0); } else { o->FogDensity = 0.20; } if ((argparser_keyword_present(pp, "-From4"))) { for (j = 0; j < 4; j++) { o->From4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From4 = (r4_t){0.0,0.0,0.0,-5.0}; } if ((argparser_keyword_present(pp, "-To4"))) { for (j = 0; j < 4; j++) { o->To4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To4 = (r4_t){0.0,0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up4"))) { for (j = 0; j < 4; j++) { o->Up4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up4 = (r4_t){0.0,1.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Over4"))) { for (j = 0; j < 4; j++) { o->Over4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Over4 = (r4_t){0.0,0.0,1.0,0.0}; } if ((argparser_keyword_present(pp, "-Vangle4"))) { o->Vangle4 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle4 = 45.0; } if ((argparser_keyword_present(pp, "-From3"))) { for (j = 0; j < 3; j++) { o->From3[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From3 = (r3_t){2.0,1.5,3.0}; } if ((argparser_keyword_present(pp, "-To3"))) { for (j = 0; j < 3; j++) { o->To3[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To3 = (r3_t){0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up3"))) { for (j = 0; j < 3; j++) { o->Up3[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up3 = (r3_t){0.0,1.0,0.0}; } if ((argparser_keyword_present(pp, "-Vangle3"))) { o->Vangle3 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle3 = 45.0; } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: SplineToWire4 \\\n" \ " [ -outFile ]\\\n" \ " [ -cp0 ] \\\n" \ " [ -cp1 ] \\\n" \ " [ -cp2 ] \\\n" \ " [ -cp3 ] \\\n" \ " [ -From4 ] \\\n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ] \\\n" \ " [ -Vangle4 ] \\\n" \ " [ -From3 ] \\\n" \ " [ -To3 ] \\\n" \ " [ -Up3 ] \\\n" \ " [ -Vangle3 ] \\\n" \ " [ -DepthCueLevels ] \\\n" \ " [ -FogDensity ]\n"); END¦ } } return o; } /* END GetOptions */ /* end BezierToWire4 */~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cur/progs-more/Build600Cell.c #define PROG_NAME "Build600Cell" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Build600Cell_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program builds the 600-cell regular polytope which has 120 nodes, 720 edges, 1200 walls and 600 tetrahedral cells. The construction basically follows the techniques so called Heegaard Decomposition that consists in the glue of two solid body called: Handlebody of genus 1. In the end we append the full description due to Don Davis that consists of gluing two solid tori of 150 tetrahedra plus a toroidal sheet of 300 tetrahedra acting as a glue layer between them. */ // #INCLUDE #include #include // #INCLUDE // #INCLUDE #include // #INCLUDE TYPE double Shape_t = { SolidTorus, HollowTorus, Tube, cell600, RowAtom, Row } typedef struct Options_t { Shape_t shape; char *shapeName; uint order; char *outFile; } @PLACE == Place_vec_t; Free == RECORD tetra : REF ARRAY OF Place_vec_t; pyram : REF ARRAY OF Place_vec_t; } void DoIt() { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? m = MakeShape(o->shape, o->order); double top = MakeElemTable(m,1); double c = GenCoords(top)^; { /* Set the "root" attribute for walls and edges. */ for (i = 0; i < top.wall.ne; i++) { ??? f = top.wall[i]; { f->root = f->num; } } for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i]; { e->root = e->num; } } WriteTopology(o->output, tag, &top, topo_cmt); // outFile Build600cell outFile WriteState( o->outFile, top, c,"Created by Build600cell: " & o->outFile \ ".st on " & Today() & "\nRandom Geometry" ); WriteMaterials(o->output, tag, &top, topo_cmt); // outFile Build600cell outFile ??? n = NumberFreeWalls(top); { fprintf(stderr,"The number or boundary walls is "&Fmt.Int(n)&"\n"); } /* tests */ for (i = 0; i < top.edge.ne; i++) { ??? e = top.edge[i].pa; { if ((Internal@{Edge->?}(e))) { assert(DegreeOfWall(e) == 5); } } } return 0; } Place_t MakeShape(shape: Shape_t; or: uint) { CASE shape OF break; case Shape_SolidTorus: ??? a = MakeSolidTorus(); { return a[0]; } break; case Shape_RowAtom: return MakeRowAtom(or); break; case Shape_HollowTorus: return MakeHollowTorus().pyram[5][5]; break; case Shape_Tube: return MakeTube(); break; case Shape_Row: return MakeRow().tetra[2][3]; break; case Shape_cell600: return Makecell600(); } } /* END MakeShape */ uint NumberFreeWalls(ElemTableRec_t *top) /* Find the number of boundary walls in the elem table "top". */ n : uint = 0; { for (i = 0; i < top->wall.ne; i++){ ??? f = top->wall[i].pa; { if (((Ppos(f) == NULL) && (Pneg(f)!=NULL) OR (Pneg(f) == NULL) && (Ppos(f)!=NULL) )){ n++; } } } return n; } /* END NumberFreeWalls */ bool_t InternalWall(f: Place_t) /* Return TRUE if wall "PWall(a)" is a internal wall */ { if (((Ppos(f) == NULL) && (Pneg(f)!=NULL) OR (Pneg(f) == NULL) && (Ppos(f)!=NULL) )){ return FALSE }else{ return TRUE; } } /* END InternalWall */ PROCEDURE Internal@{Edge->?}(Place_t @p) : bool_t == /* Return TRUE if @{edge->?} "PEdge(a)" is a internal @{edge->?} */ VAR Place_t an = a; bool_t re = TRUE; { do { if ((! InternalWall(an))){ re = FALSE; EXIT; } an = NextF(an); } while (an != a); return re; } /* END Internal@{Edge->?} */ Place_t Makecell600() { ??? h = MakeHollowTorus(); ??? s1 = MakeSolidTorus(); ??? s2 = MakeSolidTorus(); { /* We attach the 100 triangular walls of the solid torus to the 100 triangular walls of the sheet's inner surface. Additionally we need more 30 glues for close the hollowtorus 10 inferior border glues more 20 left side glues. */ /* 1 */ /* RescueOnWall (Spin(NextE (h.pyram[0][6])), s1[0]); */ Glue (Spin(NextE (h.pyram[0][6])), s1[0], 1); /* RescueOnWall (Spin(NextE (h.pyram[11][6])),s1[1]); */ Glue (Spin(NextE (h.pyram[11][6])),s1[1], 1); /* RescueOnWall (Spin(NextE (h.pyram[22][6])),s1[2]); */ Glue (Spin(NextE (h.pyram[22][6])),s1[2], 1); /* RescueOnWall (Spin(NextE (h.pyram[33][6])),s1[3]); */ Glue (Spin(NextE (h.pyram[33][6])),s1[3], 1); /* RescueOnWall (Spin(NextE (h.pyram[44][6])),s1[4]); */ Glue (Spin(NextE (h.pyram[44][6])),s1[4], 1); /* RescueOnWall (Clock(PrevE(h.pyram[10][2])),s1[5]); */ Glue (Clock(PrevE(h.pyram[10][2])),s1[5], 1); /* RescueOnWall (Clock(PrevE(h.pyram[21][2])),s1[6]); */ Glue (Clock(PrevE(h.pyram[21][2])),s1[6], 1); /* RescueOnWall (Clock(PrevE(h.pyram[32][2])),s1[7]); */ Glue (Clock(PrevE(h.pyram[32][2])),s1[7], 1); /* RescueOnWall (Clock(PrevE(h.pyram[43][2])),s1[8]); */ Glue (Clock(PrevE(h.pyram[43][2])),s1[8], 1); /* RescueOnWall (Clock(PrevE(h.pyram[54][2])),s1[9]); */ Glue (Clock(PrevE(h.pyram[54][2])),s1[9], 1); /* 2 */ /* RescueOnWall (Spin(NextE (h.pyram[10][6])),s1[10]); */ Glue (Spin(NextE (h.pyram[10][6])),s1[10], 1); /* RescueOnWall (Spin(NextE (h.pyram[21][6])),s1[11]); */ Glue (Spin(NextE (h.pyram[21][6])),s1[11], 1); /* RescueOnWall (Spin(NextE (h.pyram[32][6])),s1[12]); */ Glue (Spin(NextE (h.pyram[32][6])),s1[12], 1); /* RescueOnWall (Spin(NextE (h.pyram[43][6])),s1[13]); */ Glue (Spin(NextE (h.pyram[43][6])),s1[13], 1); /* RescueOnWall (Spin(NextE (h.pyram[54][6])),s1[14]); */ Glue (Spin(NextE (h.pyram[54][6])),s1[14], 1); /* RescueOnWall (Clock(PrevE(h.pyram[20][2])),s1[15]); */ Glue (Clock(PrevE(h.pyram[20][2])),s1[15], 1); /* RescueOnWall (Clock(PrevE(h.pyram[31][2])),s1[16]); */ Glue (Clock(PrevE(h.pyram[31][2])),s1[16], 1); /* RescueOnWall (Clock(PrevE(h.pyram[42][2])),s1[17]); */ Glue (Clock(PrevE(h.pyram[42][2])),s1[17], 1); /* RescueOnWall (Clock(PrevE(h.pyram[53][2])),s1[18]); */ Glue (Clock(PrevE(h.pyram[53][2])),s1[18], 1); /* RescueOnWall (Clock(PrevE(h.pyram[64][2])),s1[19]); */ Glue (Clock(PrevE(h.pyram[64][2])),s1[19], 1); /* 3 */ /* RescueOnWall (Spin(NextE (h.pyram[20][6])),s1[20]); */ Glue (Spin(NextE (h.pyram[20][6])),s1[20], 1); /* RescueOnWall (Spin(NextE (h.pyram[31][6])),s1[21]); */ Glue (Spin(NextE (h.pyram[31][6])),s1[21], 1); /* RescueOnWall (Spin(NextE (h.pyram[42][6])),s1[22]); */ Glue (Spin(NextE (h.pyram[42][6])),s1[22], 1); /* RescueOnWall (Spin(NextE (h.pyram[53][6])),s1[23]); */ Glue (Spin(NextE (h.pyram[53][6])),s1[23], 1); /* RescueOnWall (Spin(NextE (h.pyram[64][6])),s1[24]); */ Glue (Spin(NextE (h.pyram[64][6])),s1[24], 1); /* RescueOnWall (Clock(PrevE(h.pyram[30][2])),s1[25]); */ Glue (Clock(PrevE(h.pyram[30][2])),s1[25], 1); /* RescueOnWall (Clock(PrevE(h.pyram[41][2])),s1[26]); */ Glue (Clock(PrevE(h.pyram[41][2])),s1[26], 1); /* RescueOnWall (Clock(PrevE(h.pyram[52][2])),s1[27]); */ Glue (Clock(PrevE(h.pyram[52][2])),s1[27], 1); /* RescueOnWall (Clock(PrevE(h.pyram[63][2])),s1[28]); */ Glue (Clock(PrevE(h.pyram[63][2])),s1[28], 1); /* RescueOnWall (Clock(PrevE(h.pyram[74][2])),s1[29]); */ Glue (Clock(PrevE(h.pyram[74][2])),s1[29], 1); /* 4 */ /* RescueOnWall (Spin(NextE (h.pyram[30][6])),s1[30]); */ Glue (Spin(NextE (h.pyram[30][6])),s1[30], 1); /* RescueOnWall (Spin(NextE (h.pyram[41][6])),s1[31]); */ Glue (Spin(NextE (h.pyram[41][6])),s1[31], 1); /* RescueOnWall (Spin(NextE (h.pyram[52][6])),s1[32]); */ Glue (Spin(NextE (h.pyram[52][6])),s1[32], 1); /* RescueOnWall (Spin(NextE (h.pyram[63][6])),s1[33]); */ Glue (Spin(NextE (h.pyram[63][6])),s1[33], 1); /* RescueOnWall (Spin(NextE (h.pyram[74][6])),s1[34]); */ Glue (Spin(NextE (h.pyram[74][6])),s1[34], 1); /* RescueOnWall (Clock(PrevE(h.pyram[40][2])),s1[35]); */ Glue (Clock(PrevE(h.pyram[40][2])),s1[35], 1); /* RescueOnWall (Clock(PrevE(h.pyram[51][2])),s1[36]); */ Glue (Clock(PrevE(h.pyram[51][2])),s1[36], 1); /* RescueOnWall (Clock(PrevE(h.pyram[62][2])),s1[37]); */ Glue (Clock(PrevE(h.pyram[62][2])),s1[37], 1); /* RescueOnWall (Clock(PrevE(h.pyram[73][2])),s1[38]); */ Glue (Clock(PrevE(h.pyram[73][2])),s1[38], 1); /* RescueOnWall (Clock(PrevE(h.pyram[84][2])),s1[39]); */ Glue (Clock(PrevE(h.pyram[84][2])),s1[39], 1); /* 5 */ /* RescueOnWall (Spin(NextE (h.pyram[40][6])),s1[40]); */ Glue (Spin(NextE (h.pyram[40][6])),s1[40], 1); /* RescueOnWall (Spin(NextE (h.pyram[51][6])),s1[41]); */ Glue (Spin(NextE (h.pyram[51][6])),s1[41], 1); /* RescueOnWall (Spin(NextE (h.pyram[62][6])),s1[42]); */ Glue (Spin(NextE (h.pyram[62][6])),s1[42], 1); /* RescueOnWall (Spin(NextE (h.pyram[73][6])),s1[43]); */ Glue (Spin(NextE (h.pyram[73][6])),s1[43], 1); /* RescueOnWall (Spin(NextE (h.pyram[84][6])),s1[44]); */ Glue (Spin(NextE (h.pyram[84][6])),s1[44], 1); /* RescueOnWall (Clock(PrevE(h.pyram[50][2])),s1[45]); */ Glue (Clock(PrevE(h.pyram[50][2])),s1[45], 1); /* RescueOnWall (Clock(PrevE(h.pyram[61][2])),s1[46]); */ Glue (Clock(PrevE(h.pyram[61][2])),s1[46], 1); /* RescueOnWall (Clock(PrevE(h.pyram[72][2])),s1[47]); */ Glue (Clock(PrevE(h.pyram[72][2])),s1[47], 1); /* RescueOnWall (Clock(PrevE(h.pyram[83][2])),s1[48]); */ Glue (Clock(PrevE(h.pyram[83][2])),s1[48], 1); /* RescueOnWall (Clock(PrevE(h.pyram[94][2])),s1[49]); */ Glue (Clock(PrevE(h.pyram[94][2])),s1[49], 1); /* 6 */ /* RescueOnWall (Spin(NextE (h.pyram[50][6])),s1[50]); */ Glue (Spin(NextE (h.pyram[50][6])),s1[50], 1); /* RescueOnWall (Spin(NextE (h.pyram[61][6])),s1[51]); */ Glue (Spin(NextE (h.pyram[61][6])),s1[51], 1); /* RescueOnWall (Spin(NextE (h.pyram[72][6])),s1[52]); */ Glue (Spin(NextE (h.pyram[72][6])),s1[52], 1); /* RescueOnWall (Spin(NextE (h.pyram[83][6])),s1[53]); */ Glue (Spin(NextE (h.pyram[83][6])),s1[53], 1); /* RescueOnWall (Spin(NextE (h.pyram[94][6])),s1[54]); */ Glue (Spin(NextE (h.pyram[94][6])),s1[54], 1); /* RescueOnWall (Clock(PrevE(h.pyram[60][2])),s1[55]); */ Glue (Clock(PrevE(h.pyram[60][2])),s1[55], 1); /* RescueOnWall (Clock(PrevE(h.pyram[71][2])),s1[56]); */ Glue (Clock(PrevE(h.pyram[71][2])),s1[56], 1); /* RescueOnWall (Clock(PrevE(h.pyram[82][2])),s1[57]); */ Glue (Clock(PrevE(h.pyram[82][2])),s1[57], 1); /* RescueOnWall (Clock(PrevE(h.pyram[93][2])),s1[58]); */ Glue (Clock(PrevE(h.pyram[93][2])),s1[58], 1); /* RescueOnWall (Clock(PrevE(h.pyram[ 4][2])),s1[59]); */ Glue (Clock(PrevE(h.pyram[ 4][2])),s1[59], 1); /* 7 */ /* RescueOnWall (Spin(NextE (h.pyram[60][6])),s1[60]); */ Glue (Spin(NextE (h.pyram[60][6])),s1[60], 1); /* RescueOnWall (Spin(NextE (h.pyram[71][6])),s1[61]); */ Glue (Spin(NextE (h.pyram[71][6])),s1[61], 1); /* RescueOnWall (Spin(NextE (h.pyram[82][6])),s1[62]); */ Glue (Spin(NextE (h.pyram[82][6])),s1[62], 1); /* RescueOnWall (Spin(NextE (h.pyram[93][6])),s1[63]); */ Glue (Spin(NextE (h.pyram[93][6])),s1[63], 1); /* RescueOnWall (Spin(NextE (h.pyram[ 4][6])),s1[64]); */ Glue (Spin(NextE (h.pyram[ 4][6])),s1[64], 1); /* RescueOnWall (Clock(PrevE(h.pyram[70][2])),s1[65]); */ Glue (Clock(PrevE(h.pyram[70][2])),s1[65], 1); /* RescueOnWall (Clock(PrevE(h.pyram[81][2])),s1[66]); */ Glue (Clock(PrevE(h.pyram[81][2])),s1[66], 1); /* RescueOnWall (Clock(PrevE(h.pyram[92][2])),s1[67]); */ Glue (Clock(PrevE(h.pyram[92][2])),s1[67], 1); /* RescueOnWall (Clock(PrevE(h.pyram[ 3][2])),s1[68]); */ Glue (Clock(PrevE(h.pyram[ 3][2])),s1[68], 1); /* RescueOnWall (Clock(PrevE(h.pyram[14][2])),s1[69]); */ Glue (Clock(PrevE(h.pyram[14][2])),s1[69], 1); /* 8 */ /* RescueOnWall (Spin(NextE (h.pyram[70][6])),s1[70]); */ Glue (Spin(NextE (h.pyram[70][6])),s1[70], 1); /* RescueOnWall (Spin(NextE (h.pyram[81][6])),s1[71]); */ Glue (Spin(NextE (h.pyram[81][6])),s1[71], 1); /* RescueOnWall (Spin(NextE (h.pyram[92][6])),s1[72]); */ Glue (Spin(NextE (h.pyram[92][6])),s1[72], 1); /* RescueOnWall (Spin(NextE (h.pyram[ 3][6])),s1[73]); */ Glue (Spin(NextE (h.pyram[ 3][6])),s1[73], 1); /* RescueOnWall (Spin(NextE (h.pyram[14][6])),s1[74]); */ Glue (Spin(NextE (h.pyram[14][6])),s1[74], 1); /* RescueOnWall (Clock(PrevE(h.pyram[80][2])),s1[75]); */ Glue (Clock(PrevE(h.pyram[80][2])),s1[75], 1); /* RescueOnWall (Clock(PrevE(h.pyram[91][2])),s1[76]); */ Glue (Clock(PrevE(h.pyram[91][2])),s1[76], 1); /* RescueOnWall (Clock(PrevE(h.pyram[ 2][2])),s1[77]); */ Glue (Clock(PrevE(h.pyram[ 2][2])),s1[77], 1); /* RescueOnWall (Clock(PrevE(h.pyram[13][2])),s1[78]); */ Glue (Clock(PrevE(h.pyram[13][2])),s1[78], 1); /* RescueOnWall (Clock(PrevE(h.pyram[24][2])),s1[79]); */ Glue (Clock(PrevE(h.pyram[24][2])),s1[79], 1); /* 9 */ /* RescueOnWall (Spin(NextE (h.pyram[80][6])),s1[80]); */ Glue (Spin(NextE (h.pyram[80][6])),s1[80], 1); /* RescueOnWall (Spin(NextE (h.pyram[91][6])),s1[81]); */ Glue (Spin(NextE (h.pyram[91][6])),s1[81], 1); /* RescueOnWall (Spin(NextE (h.pyram[ 2][6])),s1[82]); */ Glue (Spin(NextE (h.pyram[ 2][6])),s1[82], 1); /* RescueOnWall (Spin(NextE (h.pyram[13][6])),s1[83]); */ Glue (Spin(NextE (h.pyram[13][6])),s1[83], 1); /* RescueOnWall (Spin(NextE (h.pyram[24][6])),s1[84]); */ Glue (Spin(NextE (h.pyram[24][6])),s1[84], 1); /* RescueOnWall (Clock(PrevE(h.pyram[90][2])),s1[85]); */ Glue (Clock(PrevE(h.pyram[90][2])),s1[85], 1); /* RescueOnWall (Clock(PrevE(h.pyram[ 1][2])),s1[86]); */ Glue (Clock(PrevE(h.pyram[ 1][2])),s1[86], 1); /* RescueOnWall (Clock(PrevE(h.pyram[12][2])),s1[87]); */ Glue (Clock(PrevE(h.pyram[12][2])),s1[87], 1); /* RescueOnWall (Clock(PrevE(h.pyram[23][2])),s1[88]); */ Glue (Clock(PrevE(h.pyram[23][2])),s1[88], 1); /* RescueOnWall (Clock(PrevE(h.pyram[34][2])),s1[89]); */ Glue (Clock(PrevE(h.pyram[34][2])),s1[89], 1); /* 10 */ /* RescueOnWall (Spin(NextE (h.pyram[90][6])),s1[90]); */ Glue (Spin(NextE (h.pyram[90][6])),s1[90], 1); /* RescueOnWall (Spin(NextE (h.pyram[ 1][6])),s1[91]); */ Glue (Spin(NextE (h.pyram[ 1][6])),s1[91], 1); /* RescueOnWall (Spin(NextE (h.pyram[12][6])),s1[92]); */ Glue (Spin(NextE (h.pyram[12][6])),s1[92], 1); /* RescueOnWall (Spin(NextE (h.pyram[23][6])),s1[93]); */ Glue (Spin(NextE (h.pyram[23][6])),s1[93], 1); /* RescueOnWall (Spin(NextE (h.pyram[34][6])),s1[94]); */ Glue (Spin(NextE (h.pyram[34][6])),s1[94], 1); /* RescueOnWall (Clock(PrevE(h.pyram[ 0][2])),s1[95]); */ Glue (Clock(PrevE(h.pyram[ 0][2])),s1[95], 1); /* RescueOnWall (Clock(PrevE(h.pyram[11][2])),s1[96]); */ Glue (Clock(PrevE(h.pyram[11][2])),s1[96], 1); /* RescueOnWall (Clock(PrevE(h.pyram[22][2])),s1[97]); */ Glue (Clock(PrevE(h.pyram[22][2])),s1[97], 1); /* RescueOnWall (Clock(PrevE(h.pyram[33][2])),s1[98]); */ Glue (Clock(PrevE(h.pyram[33][2])),s1[98], 1); /* RescueOnWall (Clock(PrevE(h.pyram[44][2])),s1[99]); */ Glue (Clock(PrevE(h.pyram[44][2])),s1[99], 1); /* gluing the left side border with the rigth side border in the toroidal sheet. */ /* RescueOnWall (Spin(PrevE(h.tetra[54][2])), h.pyram[0][7]); */ Glue (Spin(PrevE(h.tetra[54][2])), h.pyram[0][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [59][7])), h.tetra[5][2]); */ Glue (Spin(NextE(h.pyram [59][7])), h.tetra[5][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[64][2])), h.pyram[10][7]); */ Glue (Spin(PrevE(h.tetra[64][2])), h.pyram[10][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [69][7])), h.tetra[15][2]); */ Glue (Spin(NextE(h.pyram [69][7])), h.tetra[15][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[74][2])), h.pyram[20][7]); */ Glue (Spin(PrevE(h.tetra[74][2])), h.pyram[20][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [79][7])), h.tetra[25][2]); */ Glue (Spin(NextE(h.pyram [79][7])), h.tetra[25][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[84][2])), h.pyram[30][7]); */ Glue (Spin(PrevE(h.tetra[84][2])), h.pyram[30][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [89][7])), h.tetra[35][2]); */ Glue (Spin(NextE(h.pyram [89][7])), h.tetra[35][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[94][2])), h.pyram[40][7]); */ Glue (Spin(PrevE(h.tetra[94][2])), h.pyram[40][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [99][7])), h.tetra[45][2]); */ Glue (Spin(NextE(h.pyram [99][7])), h.tetra[45][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[4][2])), h.pyram[50][7]); */ Glue (Spin(PrevE(h.tetra[4][2])), h.pyram[50][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [9][7])), h.tetra[55][2]); */ Glue (Spin(NextE(h.pyram [9][7])), h.tetra[55][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[14][2])), h.pyram[60][7]); */ Glue (Spin(PrevE(h.tetra[14][2])), h.pyram[60][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [19][7])), h.tetra[65][2]); */ Glue (Spin(NextE(h.pyram[ 19][7])), h.tetra[65][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[24][2])), h.pyram[70][7]); */ Glue (Spin(PrevE(h.tetra[24][2])), h.pyram[70][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [29][7])), h.tetra[75][2]); */ Glue (Spin(NextE(h.pyram [29][7])), h.tetra[75][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[34][2])), h.pyram[80][7]); */ Glue (Spin(PrevE(h.tetra[34][2])), h.pyram[80][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [39][7])), h.tetra[85][2]); */ Glue (Spin(NextE(h.pyram [39][7])), h.tetra[85][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[44][2])), h.pyram[90][7]); */ Glue (Spin(PrevE(h.tetra[44][2])), h.pyram[90][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [49][7])), h.tetra[95][2]); */ Glue (Spin(NextE(h.pyram [49][7])), h.tetra[95][2], 1); /* gluing the botton border with the top border in the toroidal sheet. */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(h.tetra[95+i][0])), h.pyram[i][3]); */ Glue (Clock(NextE(h.tetra[95+i][0])), h.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(h.pyram[i+95][5])), h.tetra[i][3]); */ Glue (Spin(NextE(h.pyram[i+95][5])), h.tetra[i][3], 1); } /* ultima etapa */ /* 1 */ /* RescueOnWall (Spin(PrevE(h.pyram[95][2])), s2[0]); */ Glue (Spin(PrevE(h.pyram[95][2])), s2[0], 1); /* RescueOnWall (Spin(PrevE(h.pyram[86][2])), s2[1]); */ Glue (Spin(PrevE(h.pyram[86][2])), s2[1], 1); /* RescueOnWall (Spin(PrevE(h.pyram[77][2])), s2[2]); */ Glue (Spin(PrevE(h.pyram[77][2])), s2[2], 1); /* RescueOnWall (Spin(PrevE(h.pyram[68][2])), s2[3]); */ Glue (Spin(PrevE(h.pyram[68][2])), s2[3], 1); /* RescueOnWall (Spin(PrevE(h.pyram[59][2])), s2[4]); */ Glue (Spin(PrevE(h.pyram[59][2])), s2[4], 1); /* RescueOnWall (Clock(NextE(h.pyram[85][6])), s2[5]); */ Glue (Clock(NextE(h.pyram[85][6])), s2[5], 1); /* RescueOnWall (Clock(NextE(h.pyram[76][6])), s2[6]); */ Glue (Clock(NextE(h.pyram[76][6])), s2[6], 1); /* RescueOnWall (Clock(NextE(h.pyram[67][6])), s2[7]); */ Glue (Clock(NextE(h.pyram[67][6])), s2[7], 1); /* RescueOnWall (Clock(NextE(h.pyram[58][6])), s2[8]); */ Glue (Clock(NextE(h.pyram[58][6])), s2[8], 1); /* RescueOnWall (Clock(NextE(h.pyram[49][6])), s2[9]); */ Glue (Clock(NextE(h.pyram[49][6])), s2[9], 1); /* 2 */ /* RescueOnWall (Spin(PrevE(h.pyram[85][2])), s2[10]); */ Glue (Spin(PrevE(h.pyram[85][2])), s2[10], 1); /* RescueOnWall (Spin(PrevE(h.pyram[76][2])), s2[11]); */ Glue (Spin(PrevE(h.pyram[76][2])), s2[11], 1); /* RescueOnWall (Spin(PrevE(h.pyram[67][2])), s2[12]); */ Glue (Spin(PrevE(h.pyram[67][2])), s2[12], 1); /* RescueOnWall (Spin(PrevE(h.pyram[58][2])), s2[13]); */ Glue (Spin(PrevE(h.pyram[58][2])), s2[13], 1); /* RescueOnWall (Spin(PrevE(h.pyram[49][2])), s2[14]); */ Glue (Spin(PrevE(h.pyram[49][2])), s2[14], 1); /* RescueOnWall (Clock(NextE(h.pyram[75][6])), s2[15]); */ Glue (Clock(NextE(h.pyram[75][6])), s2[15], 1); /* RescueOnWall (Clock(NextE(h.pyram[66][6])), s2[16]); */ Glue (Clock(NextE(h.pyram[66][6])), s2[16], 1); /* RescueOnWall (Clock(NextE(h.pyram[57][6])), s2[17]); */ Glue (Clock(NextE(h.pyram[57][6])), s2[17], 1); /* RescueOnWall (Clock(NextE(h.pyram[48][6])), s2[18]); */ Glue (Clock(NextE(h.pyram[48][6])), s2[18], 1); /* RescueOnWall (Clock(NextE(h.pyram[39][6])), s2[19]); */ Glue (Clock(NextE(h.pyram[39][6])), s2[19], 1); /* 3 */ /* RescueOnWall (Spin(PrevE(h.pyram[75][2])), s2[20]); */ Glue (Spin(PrevE(h.pyram[75][2])), s2[20], 1); /* RescueOnWall (Spin(PrevE(h.pyram[66][2])), s2[21]); */ Glue (Spin(PrevE(h.pyram[66][2])), s2[21], 1); /* RescueOnWall (Spin(PrevE(h.pyram[57][2])), s2[22]); */ Glue (Spin(PrevE(h.pyram[57][2])), s2[22], 1); /* RescueOnWall (Spin(PrevE(h.pyram[48][2])), s2[23]); */ Glue (Spin(PrevE(h.pyram[48][2])), s2[23], 1); /* RescueOnWall (Spin(PrevE(h.pyram[39][2])), s2[24]); */ Glue (Spin(PrevE(h.pyram[39][2])), s2[24], 1); /* RescueOnWall (Clock(NextE(h.pyram[65][6])), s2[25]); */ Glue (Clock(NextE(h.pyram[65][6])), s2[25], 1); /* RescueOnWall (Clock(NextE(h.pyram[56][6])), s2[26]); */ Glue (Clock(NextE(h.pyram[56][6])), s2[26], 1); /* RescueOnWall (Clock(NextE(h.pyram[47][6])), s2[27]); */ Glue (Clock(NextE(h.pyram[47][6])), s2[27], 1); /* RescueOnWall (Clock(NextE(h.pyram[38][6])), s2[28]); */ Glue (Clock(NextE(h.pyram[38][6])), s2[28], 1); /* RescueOnWall (Clock(NextE(h.pyram[29][6])), s2[29]); */ Glue (Clock(NextE(h.pyram[29][6])), s2[29], 1); /* 4 */ /* RescueOnWall (Spin(PrevE(h.pyram[65][2])), s2[30]); */ Glue (Spin(PrevE(h.pyram[65][2])), s2[30], 1); /* RescueOnWall (Spin(PrevE(h.pyram[56][2])), s2[31]); */ Glue (Spin(PrevE(h.pyram[56][2])), s2[31], 1); /* RescueOnWall (Spin(PrevE(h.pyram[47][2])), s2[32]); */ Glue (Spin(PrevE(h.pyram[47][2])), s2[32], 1); /* RescueOnWall (Spin(PrevE(h.pyram[38][2])), s2[33]); */ Glue (Spin(PrevE(h.pyram[38][2])), s2[33], 1); /* RescueOnWall (Spin(PrevE(h.pyram[29][2])), s2[34]); */ Glue (Spin(PrevE(h.pyram[29][2])), s2[34], 1); /* RescueOnWall (Clock(NextE(h.pyram[55][6])), s2[35]); */ Glue (Clock(NextE(h.pyram[55][6])), s2[35], 1); /* RescueOnWall (Clock(NextE(h.pyram[46][6])), s2[36]); */ Glue (Clock(NextE(h.pyram[46][6])), s2[36], 1); /* RescueOnWall (Clock(NextE(h.pyram[37][6])), s2[37]); */ Glue (Clock(NextE(h.pyram[37][6])), s2[37], 1); /* RescueOnWall (Clock(NextE(h.pyram[28][6])), s2[38]); */ Glue (Clock(NextE(h.pyram[28][6])), s2[38], 1); /* RescueOnWall (Clock(NextE(h.pyram[19][6])), s2[39]); */ Glue (Clock(NextE(h.pyram[19][6])), s2[39], 1); /* 5 */ /* RescueOnWall (Spin(PrevE(h.pyram[55][2])), s2[40]); */ Glue (Spin(PrevE(h.pyram[55][2])), s2[40], 1); /* RescueOnWall (Spin(PrevE(h.pyram[46][2])), s2[41]); */ Glue (Spin(PrevE(h.pyram[46][2])), s2[41], 1); /* RescueOnWall (Spin(PrevE(h.pyram[37][2])), s2[42]); */ Glue (Spin(PrevE(h.pyram[37][2])), s2[42], 1); /* RescueOnWall (Spin(PrevE(h.pyram[28][2])), s2[43]); */ Glue (Spin(PrevE(h.pyram[28][2])), s2[43], 1); /* RescueOnWall (Spin(PrevE(h.pyram[19][2])), s2[44]); */ Glue (Spin(PrevE(h.pyram[19][2])), s2[44], 1); /* RescueOnWall (Clock(NextE(h.pyram[45][6])), s2[45]); */ Glue (Clock(NextE(h.pyram[45][6])), s2[45], 1); /* RescueOnWall (Clock(NextE(h.pyram[36][6])), s2[46]); */ Glue (Clock(NextE(h.pyram[36][6])), s2[46], 1); /* RescueOnWall (Clock(NextE(h.pyram[27][6])), s2[47]); */ Glue (Clock(NextE(h.pyram[27][6])), s2[47], 1); /* RescueOnWall (Clock(NextE(h.pyram[18][6])), s2[48]); */ Glue (Clock(NextE(h.pyram[18][6])), s2[48], 1); /* RescueOnWall (Clock(NextE(h.pyram[ 9][6])), s2[49]); */ Glue (Clock(NextE(h.pyram[ 9][6])), s2[49], 1); /* 6 */ /* RescueOnWall (Spin(PrevE(h.pyram[45][2])), s2[50]); */ Glue (Spin(PrevE(h.pyram[45][2])), s2[50], 1); /* RescueOnWall (Spin(PrevE(h.pyram[36][2])), s2[51]); */ Glue (Spin(PrevE(h.pyram[36][2])), s2[51], 1); /* RescueOnWall (Spin(PrevE(h.pyram[27][2])), s2[52]); */ Glue (Spin(PrevE(h.pyram[27][2])), s2[52], 1); /* RescueOnWall (Spin(PrevE(h.pyram[18][2])), s2[53]); */ Glue (Spin(PrevE(h.pyram[18][2])), s2[53], 1); /* RescueOnWall (Spin(PrevE(h.pyram[ 9][2])), s2[54]); */ Glue (Spin(PrevE(h.pyram[ 9][2])), s2[54], 1); /* RescueOnWall (Clock(NextE(h.pyram[35][6])), s2[55]); */ Glue (Clock(NextE(h.pyram[35][6])), s2[55], 1); /* RescueOnWall (Clock(NextE(h.pyram[26][6])), s2[56]); */ Glue (Clock(NextE(h.pyram[26][6])), s2[56], 1); /* RescueOnWall (Clock(NextE(h.pyram[17][6])), s2[57]); */ Glue (Clock(NextE(h.pyram[17][6])), s2[57], 1); /* RescueOnWall (Clock(NextE(h.pyram[ 8][6])), s2[58]); */ Glue (Clock(NextE(h.pyram[ 8][6])), s2[58], 1); /* RescueOnWall (Clock(NextE(h.pyram[99][6])), s2[59]); */ Glue (Clock(NextE(h.pyram[99][6])), s2[59], 1); /* 7 */ /* RescueOnWall (Spin(PrevE(h.pyram[35][2])), s2[60]); */ Glue (Spin(PrevE(h.pyram[35][2])), s2[60], 1); /* RescueOnWall (Spin(PrevE(h.pyram[26][2])), s2[61]); */ Glue (Spin(PrevE(h.pyram[26][2])), s2[61], 1); /* RescueOnWall (Spin(PrevE(h.pyram[17][2])), s2[62]); */ Glue (Spin(PrevE(h.pyram[17][2])), s2[62], 1); /* RescueOnWall (Spin(PrevE(h.pyram[ 8][2])), s2[63]); */ Glue (Spin(PrevE(h.pyram[ 8][2])), s2[63], 1); /* RescueOnWall (Spin(PrevE(h.pyram[99][2])), s2[64]); */ Glue (Spin(PrevE(h.pyram[99][2])), s2[64], 1); /* RescueOnWall (Clock(NextE(h.pyram[25][6])), s2[65]); */ Glue (Clock(NextE(h.pyram[25][6])), s2[65], 1); /* RescueOnWall (Clock(NextE(h.pyram[16][6])), s2[66]); */ Glue (Clock(NextE(h.pyram[16][6])), s2[66], 1); /* RescueOnWall (Clock(NextE(h.pyram[ 7][6])), s2[67]); */ Glue (Clock(NextE(h.pyram[ 7][6])), s2[67], 1); /* RescueOnWall (Clock(NextE(h.pyram[98][6])), s2[68]); */ Glue (Clock(NextE(h.pyram[98][6])), s2[68], 1); /* RescueOnWall (Clock(NextE(h.pyram[89][6])), s2[69]); */ Glue (Clock(NextE(h.pyram[89][6])), s2[69], 1); /* 8 */ /* RescueOnWall (Spin(PrevE(h.pyram[25][2])), s2[70]); */ Glue (Spin(PrevE(h.pyram[25][2])), s2[70], 1); /* RescueOnWall (Spin(PrevE(h.pyram[16][2])), s2[71]); */ Glue (Spin(PrevE(h.pyram[16][2])), s2[71], 1); /* RescueOnWall (Spin(PrevE(h.pyram[ 7][2])), s2[72]); */ Glue (Spin(PrevE(h.pyram[ 7][2])), s2[72], 1); /* RescueOnWall (Spin(PrevE(h.pyram[98][2])), s2[73]); */ Glue (Spin(PrevE(h.pyram[98][2])), s2[73], 1); /* RescueOnWall (Spin(PrevE(h.pyram[89][2])), s2[74]); */ Glue (Spin(PrevE(h.pyram[89][2])), s2[74], 1); /* RescueOnWall (Clock(NextE(h.pyram[15][6])), s2[75]); */ Glue (Clock(NextE(h.pyram[15][6])), s2[75], 1); /* RescueOnWall (Clock(NextE(h.pyram[ 6][6])), s2[76]); */ Glue (Clock(NextE(h.pyram[ 6][6])), s2[76], 1); /* RescueOnWall (Clock(NextE(h.pyram[97][6])), s2[77]); */ Glue (Clock(NextE(h.pyram[97][6])), s2[77], 1); /* RescueOnWall (Clock(NextE(h.pyram[88][6])), s2[78]); */ Glue (Clock(NextE(h.pyram[88][6])), s2[78], 1); /* RescueOnWall (Clock(NextE(h.pyram[79][6])), s2[79]); */ Glue (Clock(NextE(h.pyram[79][6])), s2[79], 1); /* 9 */ /* RescueOnWall (Spin(PrevE(h.pyram[15][2])), s2[80]); */ Glue (Spin(PrevE(h.pyram[15][2])), s2[80], 1); /* RescueOnWall (Spin(PrevE(h.pyram[ 6][2])), s2[81]); */ Glue (Spin(PrevE(h.pyram[ 6][2])), s2[81], 1); /* RescueOnWall (Spin(PrevE(h.pyram[97][2])), s2[82]); */ Glue (Spin(PrevE(h.pyram[97][2])), s2[82], 1); /* RescueOnWall (Spin(PrevE(h.pyram[88][2])), s2[83]); */ Glue (Spin(PrevE(h.pyram[88][2])), s2[83], 1); /* RescueOnWall (Spin(PrevE(h.pyram[79][2])), s2[84]); */ Glue (Spin(PrevE(h.pyram[79][2])), s2[84], 1); /* RescueOnWall (Clock(NextE(h.pyram[ 5][6])), s2[85]); */ Glue (Clock(NextE(h.pyram[ 5][6])), s2[85], 1); /* RescueOnWall (Clock(NextE(h.pyram[96][6])), s2[86]); */ Glue (Clock(NextE(h.pyram[96][6])), s2[86], 1); /* RescueOnWall (Clock(NextE(h.pyram[87][6])), s2[87]); */ Glue (Clock(NextE(h.pyram[87][6])), s2[87], 1); /* RescueOnWall (Clock(NextE(h.pyram[78][6])), s2[88]); */ Glue (Clock(NextE(h.pyram[78][6])), s2[88], 1); /* RescueOnWall (Clock(NextE(h.pyram[69][6])), s2[89]); */ Glue (Clock(NextE(h.pyram[69][6])), s2[89], 1); /* 10 */ /* RescueOnWall (Spin(PrevE(h.pyram[ 5][2])), s2[90]); */ Glue (Spin(PrevE(h.pyram[ 5][2])), s2[90], 1); /* RescueOnWall (Spin(PrevE(h.pyram[96][2])), s2[91]); */ Glue (Spin(PrevE(h.pyram[96][2])), s2[91], 1); /* RescueOnWall (Spin(PrevE(h.pyram[87][2])), s2[92]); */ Glue (Spin(PrevE(h.pyram[87][2])), s2[92], 1); /* RescueOnWall (Spin(PrevE(h.pyram[78][2])), s2[93]); */ Glue (Spin(PrevE(h.pyram[78][2])), s2[93], 1); /* RescueOnWall (Spin(PrevE(h.pyram[69][2])), s2[94]); */ Glue (Spin(PrevE(h.pyram[69][2])), s2[94], 1); /* RescueOnWall (Clock(NextE(h.pyram[95][6])), s2[95]); */ Glue (Clock(NextE(h.pyram[95][6])), s2[95], 1); /* RescueOnWall (Clock(NextE(h.pyram[86][6])), s2[96]); */ Glue (Clock(NextE(h.pyram[86][6])), s2[96], 1); /* RescueOnWall (Clock(NextE(h.pyram[77][6])), s2[97]); */ Glue (Clock(NextE(h.pyram[77][6])), s2[97], 1); /* RescueOnWall (Clock(NextE(h.pyram[68][6])), s2[98]); */ Glue (Clock(NextE(h.pyram[68][6])), s2[98], 1); /* RescueOnWall (Clock(NextE(h.pyram[59][6])), s2[99]); */ Glue (Clock(NextE(h.pyram[59][6])), s2[99], 1); return h.pyram[10][2]; } } /* END Makecell600 */ Free MakeHollowTorus() /* Build a hollow toroidal sheet, with 300 tetrahedra. */ Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 100, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 100, 8); ??? r1 = MakeRow(); ??? r2 = MakeRow(); ??? r3 = MakeRow(); ??? r4 = MakeRow(); ??? r5 = MakeRow(); ??? r6 = MakeRow(); ??? r7 = MakeRow(); ??? r8 = MakeRow(); ??? r9 = MakeRow(); ??? r10 = MakeRow(); { /* r1 <---> r2 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r1.tetra[i+5][0])), r2.pyram[i][3]); */ Glue (Clock(NextE(r1.tetra[i+5][0])), r2.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r1.pyram[i+5][5])), r2.tetra[i][3]); */ Glue (Spin(NextE(r1.pyram[i+5][5])), r2.tetra[i][3], 1); } /* r2 <---> r3 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r2.tetra[i+5][0])), r3.pyram[i][3]); */ Glue (Clock(NextE(r2.tetra[i+5][0])), r3.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r2.pyram[i+5][5])), r3.tetra[i][3]); */ Glue (Spin(NextE(r2.pyram[i+5][5])), r3.tetra[i][3], 1); } /* r3 <---> r4 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r3.tetra[i+5][0])), r4.pyram[i][3]); */ Glue (Clock(NextE(r3.tetra[i+5][0])), r4.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r3.pyram[i+5][5])), r4.tetra[i][3]); */ Glue (Spin(NextE(r3.pyram[i+5][5])), r4.tetra[i][3], 1); } /* r4 <---> r5 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r4.tetra[i+5][0])), r5.pyram[i][3]); */ Glue (Clock(NextE(r4.tetra[i+5][0])), r5.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r4.pyram[i+5][5])), r5.tetra[i][3]); */ Glue (Spin(NextE(r4.pyram[i+5][5])), r5.tetra[i][3], 1); } /* r5 <---> r6 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r5.tetra[i+5][0])), r6.pyram[i][3]); */ Glue (Clock(NextE(r5.tetra[i+5][0])), r6.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r5.pyram[i+5][5])), r6.tetra[i][3]); */ Glue (Spin(NextE(r5.pyram[i+5][5])), r6.tetra[i][3], 1); } /* r6 <---> r7 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r6.tetra[i+5][0])), r7.pyram[i][3]); */ Glue (Clock(NextE(r6.tetra[i+5][0])), r7.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r6.pyram[i+5][5])), r7.tetra[i][3]); */ Glue (Spin(NextE(r6.pyram[i+5][5])), r7.tetra[i][3], 1); } /* r7 <---> r8 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r7.tetra[i+5][0])), r8.pyram[i][3]); */ Glue (Clock(NextE(r7.tetra[i+5][0])), r8.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r7.pyram[i+5][5])), r8.tetra[i][3]); */ Glue (Spin(NextE(r7.pyram[i+5][5])), r8.tetra[i][3], 1); } /* r8 <---> r9 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r8.tetra[i+5][0])), r9.pyram[i][3]); */ Glue (Clock(NextE(r8.tetra[i+5][0])), r9.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r8.pyram[i+5][5])), r9.tetra[i][3]); */ Glue (Spin(NextE(r8.pyram[i+5][5])), r9.tetra[i][3], 1); } /* r9 <---> r10 */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(r9.tetra[i+5][0])), r10.pyram[i][3]); */ Glue (Clock(NextE(r9.tetra[i+5][0])), r10.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(r9.pyram[i+5][5])), r10.tetra[i][3]); */ Glue (Spin(NextE(r9.pyram[i+5][5])), r10.tetra[i][3], 1); } for (i = 0; i < 10; i++) { f.pyram[i] = r1.pyram[i]; f.tetra[i] = r1.tetra[i]; } for (i = 10; i < 20; i++) { f.pyram[i] = r2.pyram[i-10]; f.tetra[i] = r2.tetra[i-10]; } for (i = 20; i <= (29); i++) { f.pyram[i] = r3.pyram[i-20]; f.tetra[i] = r3.tetra[i-20]; } for (i = 30; i <= (39); i++) { f.pyram[i] = r4.pyram[i-30]; f.tetra[i] = r4.tetra[i-30]; } for (i = 40; i <= (49); i++) { f.pyram[i] = r5.pyram[i-40]; f.tetra[i] = r5.tetra[i-40]; } for (i = 50; i < 60; i++) { f.pyram[i] = r6.pyram[i-50]; f.tetra[i] = r6.tetra[i-50]; } for (i = 60; i <= (69); i++) { f.pyram[i] = r7.pyram[i-60]; f.tetra[i] = r7.tetra[i-60]; } for (i = 70; i <= (79); i++) { f.pyram[i] = r8.pyram[i-70]; f.tetra[i] = r8.tetra[i-70]; } for (i = 80; i <= (89); i++) { f.pyram[i] = r9.pyram[i-80]; f.tetra[i] = r9.tetra[i-80]; } for (i = 90; i <= (99); i++) { f.pyram[i] = r10.pyram[i-90]; f.tetra[i] = r10.tetra[i-90]; } /* some useful assertions */ /* inferior grid */ for (j = 0; j < 5; j++) { for (i = 0; i <= (8); i++) { assert(NextF(f.pyram[(i+1)*10+j,2]) == Clock(PrevE(f.pyram[i*(10)+j,6]))); } } /* superior grid */ for (j = 5; j < 10; j++) { for (i = 0; i <= (8); i++) { assert(NextF(f.pyram[(i+1)*10+j,2]) == Clock(PrevE(f.pyram[(i*10)+j,6]))); } } return f; } } /* END MakeHollowTorus */ Place_t MakeTube() { ??? h = MakeHollowTorus(); { /* gluing the left side border with the rigth side border in the toroidal sheet. */ /* RescueOnWall (Spin(PrevE(h.tetra[54][2])), h.pyram[0][7]); */ Glue (Spin(PrevE(h.tetra[54][2])), h.pyram[0][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [59][7])), h.tetra[5][2]); */ Glue (Spin(NextE(h.pyram [59][7])), h.tetra[5][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[64][2])), h.pyram[10][7]); */ Glue (Spin(PrevE(h.tetra[64][2])), h.pyram[10][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [69][7])), h.tetra[15][2]); */ Glue (Spin(NextE(h.pyram [69][7])), h.tetra[15][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[74][2])), h.pyram[20][7]); */ Glue (Spin(PrevE(h.tetra[74][2])), h.pyram[20][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [79][7])), h.tetra[25][2]); */ Glue (Spin(NextE(h.pyram [79][7])), h.tetra[25][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[84][2])), h.pyram[30][7]); */ Glue (Spin(PrevE(h.tetra[84][2])), h.pyram[30][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [89][7])), h.tetra[35][2]); */ Glue (Spin(NextE(h.pyram [89][7])), h.tetra[35][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[94][2])), h.pyram[40][7]); */ Glue (Spin(PrevE(h.tetra[94][2])), h.pyram[40][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [99][7])), h.tetra[45][2]); */ Glue (Spin(NextE(h.pyram [99][7])), h.tetra[45][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[4][2])), h.pyram[50][7]); */ Glue (Spin(PrevE(h.tetra[4][2])), h.pyram[50][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [9][7])), h.tetra[55][2]); */ Glue (Spin(NextE(h.pyram [9][7])), h.tetra[55][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[14][2])), h.pyram[60][7]); */ Glue (Spin(PrevE(h.tetra[14][2])), h.pyram[60][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [19][7])), h.tetra[65][2]); */ Glue (Spin(NextE(h.pyram[ 19][7])), h.tetra[65][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[24][2])), h.pyram[70][7]); */ Glue (Spin(PrevE(h.tetra[24][2])), h.pyram[70][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [29][7])), h.tetra[75][2]); */ Glue (Spin(NextE(h.pyram [29][7])), h.tetra[75][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[34][2])), h.pyram[80][7]); */ Glue (Spin(PrevE(h.tetra[34][2])), h.pyram[80][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [39][7])), h.tetra[85][2]); */ Glue (Spin(NextE(h.pyram [39][7])), h.tetra[85][2], 1); /* RescueOnWall (Spin(PrevE(h.tetra[44][2])), h.pyram[90][7]); */ Glue (Spin(PrevE(h.tetra[44][2])), h.pyram[90][7], 1); /* RescueOnWall (Spin(NextE(h.pyram [49][7])), h.tetra[95][2]); */ Glue (Spin(NextE(h.pyram [49][7])), h.tetra[95][2], 1); /* gluing the botton border with the top border in the toroidal sheet. */ for (i = 0; i < 5; i++) { /* RescueOnWall (Clock(NextE(h.tetra[95+i][0])), h.pyram[i][3]); */ Glue (Clock(NextE(h.tetra[95+i][0])), h.pyram[i][3], 1); /* RescueOnWall (Spin(NextE(h.pyram[i+95][5])), h.tetra[i][3]); */ Glue (Spin(NextE(h.pyram[i+95][5])), h.tetra[i][3], 1); } return h.pyram[10][2] } } /* END MakeTube */ Free MakeRow() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 10, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 10, 8); ??? p1 = MakeRowAtom5(); ??? p2 = MakeRowAtom5(); { /* gluings: p1.pyram[0][5] p2.tetra[4][3] p1.tetra[0][0] p2.pyram[4][3] p1.pyram[1][5] p2.tetra[3][3] p1.tetra[1][0] p2.pyram[3][3] p1.pyram[2][5] p2.tetra[2][3] p1.tetra[2][0] p2.pyram[2][3] p1.pyram[3][5] p2.tetra[1][3] p1.tetra[3][0] p2.pyram[1][3] p1.pyram[4][5] p2.tetra[0][3] p1.tetra[4][0] p2.pyram[0][3] */ for (i = 0; i < 5; i++) { /* RescueOnWall (Spin(p1.pyram[i][5]), PrevE(p2.tetra[4-i][3]));*/ Glue (Spin(p1.pyram[i][5]), PrevE(p2.tetra[4-i][3]), 1); /* RescueOnWall (Clock(NextE(p2.pyram[4-i][3])), p1.tetra[i][0]); */ Glue (Clock(NextE(p2.pyram[4-i][3])), p1.tetra[i][0], 1); } for (i = 0; i < 5; i++) { f.pyram[i] = p1.pyram[i]; f.tetra[i] = p1.tetra[i]; } for (i = 5; i < 10; i++) { f.pyram[i] = p2.pyram[9-i]; f.tetra[i] = p2.tetra[9-i]; } /* assertions */ for (i = 0; i < 5; i++) { assert(NextF(NextE(f.pyram[i,6])) == Clock(PrevE(f.pyram[i,2]))); } for (i = 5; i < 10; i++) { assert(NextF(NextE(f.pyram[i,6])) == Clock(PrevE(f.pyram[i,2]))); } return f; } } /* END MakeRow */ Free MakeRowAtom1() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 1, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 1, 8); ??? g = GluePyramidTetra(); { f.pyram[0] = g.pyram[0]; f.tetra[0] = g.tetra[0]; return f; } } /* END MakeRowAtom1 */ Free MakeRowAtom2() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 2, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 2, 8); ??? g = GluePyramidTetra(); ??? r = MakeRowAtom1(); { /* only one gluing g <---> r g.pyram[0][7] <--> r.tetra[0][2] */ /* RescueOnWall(Spin(g.pyram[0][7]), PrevE(r.tetra[0][2])); */ Glue (Spin(g.pyram[0][7]), PrevE(r.tetra[0][2]), 1); f.pyram[0] = r.pyram[0]; f.tetra[0] = r.tetra[0]; f.pyram[1] = g.pyram[0]; f.tetra[1] = g.tetra[0]; return f; } } /* END MakeRowAtom2 */ Free MakeRowAtom3() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 3, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 3, 8); ??? g = GluePyramidTetra(); ??? r = MakeRowAtom2(); { /* only one gluing g <---> r g.pyram[0][7] <--> r.tetra[1][2] */ /* RescueOnWall(Spin(g.pyram[0][7]), PrevE(r.tetra[1][2])); */ Glue (Spin(g.pyram[0][7]), PrevE(r.tetra[1][2]), 1); for (i = 0; i < 2; i++) { f.pyram[i] = r.pyram[i]; f.tetra[i] = r.tetra[i]; } f.pyram[2] = g.pyram[0]; f.tetra[2] = g.tetra[0]; return f; } } /* END MakeRowAtom3 */ Free MakeRowAtom4() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 4, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 4, 8); ??? g = GluePyramidTetra(); ??? r = MakeRowAtom3(); { /* only one gluing g <---> r g.pyram[0][7] <--> r.tetra[2][2] */ /* RescueOnWall(Spin(g.pyram[0][7]), PrevE(r.tetra[2][2])); */ Glue (Spin(g.pyram[0][7]), PrevE(r.tetra[2][2]), 1); for (i = 0; i < 3; i++) { f.pyram[i] = r.pyram[i]; f.tetra[i] = r.tetra[i]; } f.pyram[3] = g.pyram[0]; f.tetra[3] = g.tetra[0]; return f; } } /* END MakeRowAtom4 */ Free MakeRowAtom5() Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 5, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 5, 8); ??? g = GluePyramidTetra(); ??? r = MakeRowAtom4(); { /* only one gluing g <---> r g.pyram[0][7] <--> r.tetra[3][2] */ /* RescueOnWall(Spin(g.pyram[0][7]), PrevE(r.tetra[3][2])); */ Glue (Spin(g.pyram[0][7]), PrevE(r.tetra[3][2]), 1); for (i = 0; i < 4; i++) { f.pyram[i] = r.pyram[i]; f.tetra[i] = r.tetra[i]; } f.pyram[4] = g.pyram[0]; f.tetra[4] = g.tetra[0]; /* assertions */ for (i = 0; i < 5; i++) { assert(NextF(NextE(f.pyram[i,6])) == Clock(PrevE(f.pyram[i,2]))); } return f; } } /* END MakeRowAtom5 */ Place_t MakeRowAtom(uint order) { CASE order OF break; case 1: return MakeRowAtom1().tetra[0][3]; break; case 2: return MakeRowAtom2().tetra[0][3]; break; case 3: return MakeRowAtom3().tetra[0][3]; break; case 4: return MakeRowAtom4().tetra[0][3]; break; case 5: return MakeRowAtom5().tetra[0][3]; } else { return Triangulation.MakeWedge(); } } /* END MakeRowAtom */ Place_vec_t *MakeSolidTorus()== VAR ico : ARRAY [0..4 ] OF ARRAY [0..19] OF Place_t; tet : ARRAY [0..49] OF ARRAY [0..7 ] OF Place_t; Place_vec_t s = Place_vec_new(100); { for (i = 0; i < 5; i++){ ico.e[i] = Squared.MakeIcosahedronTriang(FALSE); } for (j = 0; j <= (49); j++) { tet[j] = MakeTetraTopo(1,1); } /* estrategia: tetrahedra 0 a 9 ligarao os icosaedros ico.e[0] e ico.e[1], tetrahedra 10 a 19 ligarao os icosaedros ico.e[1] e ico.e[2], tetrahedra 20 a 29 ligarao os icosaedros ico.e[2] e ico.e[3], tetrahedra 30 a 39 ligarao os icosaedros ico.e[3] e ico.e[4], tetrahedra 40 a 49 ligarao os icosaedros ico.e[4] e ico.e[0] */ /* @{link->?} the tetrahedra 0-4 with the superior extremum of ico.e[0] pattern: tet[2] <--> ico.e[3] */ for (i = 0; i < 5; i++) { Glue(Spin(ico.e[0][15+i]), tet[i,2], 1); } /* @{link->?} the tetrahedra 5-9 com o extremo inferior de ico.e[1] pattern: tet[3] <--> ico.e[2] */ for (i = 5; i < 10; i++) { Glue(Spin(ico.e[1][i-5]) , tet[i,3], 1); } /* @{link->?} superior extremum of ico.e[0] with the inferior extremum of ico.e[1] */ /* RescueOnWall(Spin(NextE(tet[5][1])), tet[0,0]); */ Glue (Spin(NextE(tet[5][1])), tet[0,0], 1); /* RescueOnWall(Spin(tet[1][1]), NextE(tet[5][0])); */ Glue (Spin(tet[1][1]), NextE(tet[5][0]),1); /* RescueOnWall(Spin(NextE(tet[6][1])), tet[1,0]); */ Glue (Spin(NextE(tet[6][1])), tet[1,0], 1); /* RescueOnWall(Spin(tet[2][1]), NextE(tet[6][0])); */ Glue (Spin(tet[2][1]), NextE(tet[6][0]),1); /* RescueOnWall(Spin(NextE(tet[7][1])), tet[2,0]); */ Glue (Spin(NextE(tet[7][1])), tet[2,0], 1); /* RescueOnWall(Spin(tet[3][1]), NextE(tet[7][0])); */ Glue (Spin(tet[3][1]), NextE(tet[7][0]),1); /* RescueOnWall(Spin(NextE(tet[8][1])), tet[3,0]); */ Glue (Spin(NextE(tet[8][1])), tet[3,0], 1); /* RescueOnWall(Spin(tet[4][1]), NextE(tet[8][0])); */ Glue (Spin(tet[4][1]), NextE(tet[8][0]),1); /* RescueOnWall(Spin(NextE(tet[9][1])), tet[4,0]); */ Glue (Spin(NextE(tet[9][1])), tet[4,0], 1); /* RescueOnWall(Spin(tet[0][1]), NextE(tet[9][0])); */ Glue (Spin(tet[0][1]), NextE(tet[9][0]),1); /* @{link->?} the tetrahedra 10-14 with the superior extremum of ico.e[1] pattern: tet[2] <--> ico.e[3] */ for (i = 10; i < 15; i++) { Glue(Spin(ico.e[1][5+i]), tet[i,2], 1); } /* @{link->?} the tetrahedra 15-19 com o extremo inferior de ico.e[2] pattern: tet[3] <--> ico.e[2] */ for (i = 15; i < 20; i++) { Glue(Spin(ico.e[2][i-15]) , tet[i,3], 1); } /* @{link->?} superior extremum of ico.e[1] with the inferior extremum of ico.e[2] */ /* RescueOnWall(Spin(NextE(tet[15][1])), tet[10,0]); */ Glue (Spin(NextE(tet[15][1])), tet[10,0], 1); /* RescueOnWall(Spin(tet[11][1]), NextE(tet[15][0])); */ Glue (Spin(tet[11][1]), NextE(tet[15][0]),1); /* RescueOnWall(Spin(NextE(tet[16][1])), tet[11,0]); */ Glue (Spin(NextE(tet[16][1])), tet[11,0], 1); /* RescueOnWall(Spin(tet[12][1]), NextE(tet[16][0])); */ Glue (Spin(tet[12][1]), NextE(tet[16][0]),1); /* RescueOnWall(Spin(NextE(tet[17][1])), tet[12,0]); */ Glue (Spin(NextE(tet[17][1])), tet[12,0], 1); /* RescueOnWall(Spin(tet[13][1]), NextE(tet[17][0])); */ Glue (Spin(tet[13][1]), NextE(tet[17][0]),1); /* RescueOnWall(Spin(NextE(tet[18][1])), tet[13,0]); */ Glue (Spin(NextE(tet[18][1])), tet[13,0], 1); /* RescueOnWall(Spin(tet[14][1]), NextE(tet[18][0])); */ Glue (Spin(tet[14][1]), NextE(tet[18][0]),1); /* RescueOnWall(Spin(NextE(tet[19][1])), tet[14,0]); */ Glue (Spin(NextE(tet[19][1])), tet[14,0], 1); /* RescueOnWall(Spin(tet[10][1]), NextE(tet[19][0])); */ Glue (Spin(tet[10][1]), NextE(tet[19][0]),1); /* @{link->?} the tetrahedra 10-14 with the superior extremum of ico.e[1] pattern: tet[2] <--> ico.e[3] */ for (i = 10; i < 15; i++) { Glue(Spin(ico.e[1][5+i]), tet[i,2], 1); } /* @{link->?} the tetrahedra 15-19 om o extremo inferior de ico.e[2] pattern: tet[3] <--> ico.e[2] */ for (i = 15; i < 20; i++) { Glue(Spin(ico.e[2][i-15]) , tet[i,3], 1); } /* @{link->?} superior extremum of ico.e[2] with the inferior extremum of ico.e[3] */ /* RescueOnWall(Spin(NextE(tet[15][1])), tet[10,0]); */ Glue (Spin(NextE(tet[15][1])), tet[10,0], 1); /* RescueOnWall(Spin(tet[11][1]), NextE(tet[15][0])); */ Glue (Spin(tet[11][1]), NextE(tet[15][0]),1); /* RescueOnWall(Spin(NextE(tet[16][1])), tet[11,0]); */ Glue (Spin(NextE(tet[16][1])), tet[11,0], 1); /* RescueOnWall(Spin(tet[12][1]), NextE(tet[16][0])); */ Glue (Spin(tet[12][1]), NextE(tet[16][0]),1); /* RescueOnWall(Spin(NextE(tet[17][1])), tet[12,0]); */ Glue (Spin(NextE(tet[17][1])), tet[12,0], 1); /* RescueOnWall(Spin(tet[13][1]), NextE(tet[17][0])); */ Glue (Spin(tet[13][1]), NextE(tet[17][0]),1); /* RescueOnWall(Spin(NextE(tet[18][1])), tet[13,0]); */ Glue (Spin(NextE(tet[18][1])), tet[13,0], 1); /* RescueOnWall(Spin(tet[14][1]), NextE(tet[18][0])); */ Glue (Spin(tet[14][1]), NextE(tet[18][0]),1); /* RescueOnWall(Spin(NextE(tet[19][1])), tet[14,0]); */ Glue (Spin(NextE(tet[19][1])), tet[14,0], 1); /* RescueOnWall(Spin(tet[10][1]), NextE(tet[19][0])); */ Glue (Spin(tet[10][1]), NextE(tet[19][0]),1); /* @{link->?} the tetrahedra 20-24 with the superior extremum of ico.e[2] pattern: tet[2] <--> ico.e[3] */ for (i = 20; i <= (24); i++) { Glue(Spin(ico.e[2][i-5]), tet[i,2], 1); } /* @{link->?} the tetrahedra 15-19 cwith the inferior extremum of ico.e[3] pattern: tet[3] <--> ico.e[2] */ for (i = 25; i <= (29); i++) { Glue(Spin(ico.e[3][i-25]) , tet[i,3], 1); } /* @{link->?} superior extremum of ico.e[3] with the inferior extremum of ico.e[4] */ /* RescueOnWall(Spin(NextE(tet[25][1])), tet[20,0]); */ Glue (Spin(NextE(tet[25][1])), tet[20,0], 1); /* RescueOnWall(Spin(tet[21][1]), NextE(tet[25][0])); */ Glue (Spin(tet[21][1]), NextE(tet[25][0]),1); /* RescueOnWall(Spin(NextE(tet[26][1])), tet[21,0]); */ Glue (Spin(NextE(tet[26][1])), tet[21,0], 1); /* RescueOnWall(Spin(tet[22][1]), NextE(tet[26][0])); */ Glue (Spin(tet[22][1]), NextE(tet[26][0]),1); /* RescueOnWall(Spin(NextE(tet[27][1])), tet[22,0]); */ Glue (Spin(NextE(tet[27][1])), tet[22,0], 1); /* RescueOnWall(Spin(tet[23][1]), NextE(tet[27][0])); */ Glue (Spin(tet[23][1]), NextE(tet[27][0]),1); /* RescueOnWall(Spin(NextE(tet[28][1])), tet[23,0]); */ Glue (Spin(NextE(tet[28][1])), tet[23,0], 1); /* RescueOnWall(Spin(tet[24][1]), NextE(tet[28][0])); */ Glue (Spin(tet[24][1]), NextE(tet[28][0]),1); /* RescueOnWall(Spin(NextE(tet[29][1])), tet[24,0]); */ Glue (Spin(NextE(tet[29][1])), tet[24,0], 1); /* RescueOnWall(Spin(tet[20][1]), NextE(tet[29][0])); */ Glue (Spin(tet[20][1]), NextE(tet[29][0]),1); /* @{link->?} the tetrahedra 30-34 with the superior extremum of ico.e[3] pattern: tet[2] <--> ico.e[3] */ for (i = 30; i <= (34); i++) { Glue(Spin(ico.e[3][i-15]), tet[i,2], 1); } /* @{link->?} the tetrahedra 35-39 with the inferior extremum of ico.e[4] pattern: tet[3] <--> ico.e[2] */ for (i = 35; i <= (39); i++) { Glue(Spin(ico.e[4][i-35]) , tet[i,3], 1); } /* @{link->?} superior extremum of ico.e[4] with the inferior extremum of ico.e[0] */ /* RescueOnWall(Spin(NextE(tet[35][1])), tet[30,0]); */ Glue (Spin(NextE(tet[35][1])), tet[30,0], 1); /* RescueOnWall(Spin(tet[31][1]), NextE(tet[35][0])); */ Glue (Spin(tet[31][1]), NextE(tet[35][0]),1); /* RescueOnWall(Spin(NextE(tet[36][1])), tet[31,0]); */ Glue (Spin(NextE(tet[36][1])), tet[31,0], 1); /* RescueOnWall(Spin(tet[32][1]), NextE(tet[36][0])); */ Glue (Spin(tet[32][1]), NextE(tet[36][0]),1); /* RescueOnWall(Spin(NextE(tet[37][1])), tet[32,0]); */ Glue (Spin(NextE(tet[37][1])), tet[32,0], 1); /* RescueOnWall(Spin(tet[33][1]), NextE(tet[37][0])); */ Glue (Spin(tet[33][1]), NextE(tet[37][0]),1); /* RescueOnWall(Spin(NextE(tet[38][1])), tet[33,0]); */ Glue (Spin(NextE(tet[38][1])), tet[33,0], 1); /* RescueOnWall(Spin(tet[34][1]), NextE(tet[38][0])); */ Glue (Spin(tet[34][1]), NextE(tet[38][0]),1); /* RescueOnWall(Spin(NextE(tet[39][1])), tet[34,0]); */ Glue (Spin(NextE(tet[39][1])), tet[34,0], 1); /* RescueOnWall(Spin(tet[30][1]), NextE(tet[39][0])); */ Glue (Spin(tet[30][1]), NextE(tet[39][0]),1); /* @{link->?} the tetrahedra 40-44 with the superior extremum of ico.e[4] pattern: tet[2] <--> ico.e[3] */ for (i = 40; i <= (44); i++) { Glue(Spin(ico.e[4][i-25]), tet[i,2], 1); } /* @{link->?} the tetrahedra 45-49 with the inferior extremum of ico.e[0] pattern: tet[3] <--> ico.e[2] */ for (i = 45; i <= (49); i++) { Glue(Spin(ico.e[0][i-45]) , tet[i,3], 1); } /* @{link->?} superior extremum of ico.e[3] with the inferior extremum of ico.e[4] */ /* RescueOnWall(Spin(NextE(tet[45][1])), tet[40,0]); */ Glue (Spin(NextE(tet[45][1])), tet[40,0], 1); /* RescueOnWall(Spin(tet[41][1]), NextE(tet[45][0])); */ Glue (Spin(tet[41][1]), NextE(tet[45][0]),1); /* RescueOnWall(Spin(NextE(tet[46][1])), tet[41,0]); */ Glue (Spin(NextE(tet[46][1])), tet[41,0], 1); /* RescueOnWall(Spin(tet[42][1]), NextE(tet[46][0])); */ Glue (Spin(tet[42][1]), NextE(tet[46][0]),1); /* RescueOnWall(Spin(NextE(tet[47][1])), tet[42,0]); */ Glue (Spin(NextE(tet[47][1])), tet[42,0], 1); /* RescueOnWall(Spin(tet[43][1]), NextE(tet[47][0])); */ Glue (Spin(tet[43][1]), NextE(tet[47][0]),1); /* RescueOnWall(Spin(NextE(tet[48][1])), tet[43,0]); */ Glue (Spin(NextE(tet[48][1])), tet[43,0], 1); /* RescueOnWall(Spin(tet[44][1]), NextE(tet[48][0])); */ Glue (Spin(tet[44][1]), NextE(tet[48][0]),1); /* RescueOnWall(Spin(NextE(tet[49][1])), tet[44,0]); */ Glue (Spin(NextE(tet[49][1])), tet[44,0], 1); /* RescueOnWall(Spin(tet[40][1]), NextE(tet[49][0])); */ Glue (Spin(tet[40][1]), NextE(tet[49][0]),1); /* the @place that will be returned as: I0 : T9-10 : I1 : T10-19 : I2 : T20-29 : I3 : T30-39 : I4 : T40-49 10 10 10 10 10 10 10 10 10 10 Fon each icosahedron the @places follow the pattern: 5 --- 6 --- 7 --- 8 --- 9 10 11 12 13 14 |_______________________| tetrahedra follow the pattern: Is -------------- T:0,1,2,3,4[3] --> free T:5,6,7,8,9[2] --- Ii --> free */ for (i = 0; i < 10; i++){ s[i] = ico.e[0][i+5]; } for (i = 20; i <= (29); i++){ s[i] = ico.e[1][i-15]; } for (i = 40; i <= (49); i++){ s[i] = ico.e[2][i-35]; } for (i = 60; i <= (69); i++){ s[i] = ico.e[3][i-55]; } for (i = 80; i <= (89); i++){ s[i] = ico.e[4][i-75]; } for (i = 10; i < 15; i++){ s[i] = tet[i-10][3]; } for (i = 15; i < 20; i++){ s[i] = tet[i-10][2]; } for (i = 30; i <= (34); i++){ s[i] = tet[i-20][3]; } for (i = 35; i <= (39); i++){ s[i] = tet[i-20][2]; } for (i = 50; i <= (54); i++){ s[i] = tet[i-30][3]; } for (i = 55; i < 60; i++){ s[i] = tet[i-30][2]; } for (i = 70; i <= (74); i++){ s[i] = tet[i-40][3]; } for (i = 75; i <= (79); i++){ s[i] = tet[i-40][2]; } for (i = 90; i <= (94); i++){ s[i] = tet[i-50][3]; } for (i = 95; i <= (99); i++){ s[i] = tet[i-50][2]; } for (i = 0; i < 5; i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 10; i < 15; i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 20; i <= (24); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 30; i <= (34); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 40; i <= (44); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 50; i <= (54); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 60; i <= (64); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 70; i <= (74); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 80; i <= (84); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 90; i <= (94); i++) { assert(NextF(NextE(s[i])) == Spin(PrevE(s[i+5]))); } for (i = 0; i < 5; i++) { assert(NextF(s[i]) == Spin(s[i+95])); } for (i = 10; i < 15; i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 20; i <= (24); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 30; i <= (34); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 40; i <= (44); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 50; i <= (54); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 60; i <= (64); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 70; i <= (74); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 80; i <= (84); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } for (i = 90; i <= (94); i++) { assert(NextF(s[i]) == Spin(s[i-5])); } return s; } MakeSolidTorus; Free MakePyramid() Free *f; { f.pyram = NEW(REF ARRAY OF Place_vec_t, 1, 8); ??? a = MakeTetraTopo(1,1); ??? b = MakeTetraTopo(1,1); { Glue(Spin(a[1]),b[0],1); for (j = 0; j < 4; j++) { f.pyram[0][j] = a[j]; } for (j = 4; j < 8; j++) { f.pyram[0][j] = b[j-4]; } } /* assertions */ assert(NextF(NextE(f.pyram[0,6])) == Clock(PrevE(f.pyram[0,2]))); return f; /* Warning: note that the @place c[1][0] == b[0] was deleted from the topology, their use will produce NULL. */ } /* END MakePyramid */ Free GluePyramidTetra() /* This procedure glue one pyramid more one tetrahedron. Note that this procedure es equal to the gluing of one tetrahedron more one pyramid. */ Free *f; { f.tetra = NEW(REF ARRAY OF Place_vec_t, 1, 4); f.pyram = NEW(REF ARRAY OF Place_vec_t, 1, 8); ??? te = MakeTetraTopo(1,1); ??? py = MakePyramid(); { /* make the gluing : py[0][0] <---> te[1] */ Glue(Spin(te[1]), py.pyram[0][0], 1); /* rescuing the @places : First the @places derived from the MakePyramid procedure. Second the @places of the tetrahedron te. */ for (i = 0; i < 8; i++) { f.pyram[0][i] = py.pyram[0][i]; } for (j = 0; j < 4; j++) { f.tetra[0][j] = te[j]; } } return f; /* Warning: note that the @places: a[0][0]==py[0][0] and a[1][0]==py[1][0], was deleted from the topology, their use will produce NULL. */ } /* END GluePyramidTetra */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "solid"))) { o->shape = Shape_SolidTorus } else if (0 == strcmp(o->shapeName, "hollow"))){ o->shape = Shape_HollowTorus } else if (0 == strcmp(o->shapeName, "cell600"))){ o->shape = Shape_cell600 } else if (0 == strcmp(o->shapeName, "rowatom"))){ o->shape = Shape_RowAtom; argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 1, 5); } else if (0 == strcmp(o->shapeName, "row"))){ o->shape = Shape_Row; } else if (0 == strcmp(o->shapeName, "tube"))){ o->shape = Shape_Tube } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n") } argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Build600Cell \\\n" \ " -shape { solid | hollow | rowatom -order | ... }\\\n" \ " -outFile \n"); END¦ } } return o; } /* END GetOptions */ /* end Build600Cell */ /*************************************************************************** From: dtd@world.std.com (Don Davis) Subject: 600-cell from two tori (long) Date: Wed, 8 Sep 1999 22:35:27 GMT Newsgroups: sci.math Keywords: construction of 120-cell and 600-cell (solids in R^4) In article <7r5bil$elq$1@mail.pl.unisys.com>, "Clive Tooth" wrote: > I wonder if the same approach could be used to illustrate the > construction of a 600-cell. My first reaction is that the tetra- > hedron is too "pointy" to make nice-looking diagrams, but maybe not... i have a more-or-less simple-to-visualize construction of the 600-cell, which i figured out last winter (it took me a while). i also found, in writing this up, that a similar construction also makes the 120-cell even easier to visualize. i have looked around on the web, and haven't seen anything as easy as my technique. i must admit i am very pleased with it. i don't have pictures yet, but here's a quickie description, without any proofs: the 600-cell construction has three parts: two solid tori of 150 cells each, and a hollow torus of 300 cells. build each solid torus as follows: using 100 tetrahedra, assemble 5 solid icosahedra (this is possible in R^4). daisy-chain five such icosahedra pole-to-pole. between every @place of adjacent icosahedra, surround the common node with 10 tetrahedra. each solid torus has a decagonal "axis" running through the centers and poles of the icosa- hedra. each solid torus contains 5*20 + 5*10 == 150 tetra- hedra, and its surface is tiled with 100 equilateral triangles. on this surface, six triangles meet at every node. we will @{link->?} these solid tori, like two @{link->?}s of a chain. with the hollow torus acting as a glue layer between them. build the hollow torus as follows: lay out a 5x10 grid of unit @{edge->?}s. omit the left-hand and lower boundaries' @{edge->?}s, because we're going to roll this grid into a torus later. thus, the grid contains 100 @{edge->?}s: 50 running N-S, and 50 running E-W. attach one tetrahedron to each @{edge->?} from above the grid. the opposite @{edge->?}s of these tetrahedra will form a new 5x10 grid, whose nodes overlie the centers of the squares in the lower grid. thus, these 100 tetrahedra now form an egg-carton shape, with 50 square-pyramid cups on each side. divide each cup into two non-unit tetrahedra, by erecting a right-triangular wall across the cup, corner-to-corner. make the upper cups' dividers run NE/SW, and make the upside-down lower cups' dividers run NW/SE. note that the egg-carton is now a solid flat layer, one tetrahedron deep, containing 100 unit tetra- hedra and 200 non-unit tetrahedra. when we shrink the right-triangular dividing walls into equilateral triangles, we distort each egg-cup into a @place of unit-tetrahedra. at the same time, the opening of each egg-cup changes from a square to a bent rhombus. as the square openings bend, the flat sheet of 300 tethrahedra is forced to wrap around into a hollow torus with a one-unit- thick shell. surprisingly, this bends each 5x10 grid into a toroidal sheet of 100 equilateral triangles. each grid's short @{edge->?} is now a pentagon that threads through the donut hole. the grid's long @{edge->?} is now a decagon that wraps around both holes in its donut. the two grids' long @{edge->?}s are now @{link->?}ed decagons. this wrapping cannot occur in R^3, but it works fine in R^4. i admit that this part of my presentation is not easy to visualize. perhaps a localized visualization image will help: as an upper egg-cup is squeezed in one direction, the edge-tetrahedra around it rotate, squeezing the nearby lower egg-cups in the other direction. this forces the flat sheet into a saddle-shape. in R^4, when this saddle-bending happens across the whole egg-carton at once, the carton's @{edge->?}s can meet to make the toroidal sheet. finally, put one solid torus inside the hollow toroidal sheet, attaching the 100 triangular walls of the solid to the 100 triangles of the sheet's inner surface. this gives us a fat solid torus, 10 units around and 4 units thick, containing 450 tetrahedral cells. nevertheless, its surface has only 100 triangular walls. thread the second 150-cell solid torus through this fat torus, and attach the two solids' triangular walls. this is the 600-cell polytope. symmetry: recall the decagonal "axes" of the original 150-cell solid tori. these two @{link->?}ed decagons are now the equators of a 3-sphere in R^4. the equators are 3 units apart. all of the grids' N/S unit @{edge->?}s are @{link->?}ed up into decagons, too. indeed, each @{edge->?} in the 600 cell is part of a unique planar decagon that girdles the figure. there are (600*6)/5 == 720 @{edge->?}s in all, so 72 such decagons criscross the 600-cell. it's a beautiful fact that these decagons can be grouped into sets of 12, s.t. the 12 decagons trace the @{link->?}ed circles of a Hopf fibration of S^3! for each of the 6 node-to- node rotational axes of the icosahedron, there are two arrangements of these 12 decagons: * through each axis there is exactly one equatorial decagon; * @{link->?}ed with this equatorial decagon are 5 decagons, wrapped around the equator in a barber-pole pattern; * 5 more decagons are wrapped around the barber-pole in the same direction, but in a shallower spiral; * the second equatorial decagon girdles the lot, in a plane perpendicular to the first equator. there are two such wrappings for each axis, because the barber pole can carry a left-handed or a right-handed stripe. thus, the 600-cell presents 12 distinct Hopf fibrations of itself. -------===========================------- in general, this "stitch 2 tori together" approach can be very natural for visualising the complicated polytopes of 3-d cells, since the tori display the S^3 symmetry enjoyed by these shapes. for example, it's nicer to con- sider the tesseract as two @{link->?}ed rings of 4 cubes, than as a russian doll of nestled cubes, or as a 3-D cross. note that the 600-cell has (600*4)/20 == 120 nodes, and it is the dual of the 120-cell. thus, it is straight- forward to assemble the 120-cell in an analogous but easier way, starting with two simple rings of 10 dodecahedra apiece. each ring has 10 neck-like indentations between @places of dodecahedra. we cover each neck with 5 dodecahedra, making two bumpy tori of 60 cells apiece. the bumps and hollows form a simple square-grid arrangement on the surface of each torus. @{link->?} these tori, and stitch them together, fitting the bumps of one torus into the hollows of the other. this bumpy interface between the two tori is a semi- regular toroidal surface, comprising 50*4 == 200 regular pentagons. three pentagons meet at each node in the concave and convex parts of the surface, but in the saddle- shaped parts, four pentagons meet at each node. when we project this tesselation onto the plane, we get a familiar tiling of irregular pentagons. in this projection, each pentagon has two right angles and three 120-degree angles, and four pentagons are arranged to form a squat hexagon. these hexagons tile the plane (and thus the toroidal surface) in the usual way (you'll need a fixed-width font here): :, ,: :, ,: :, ,: __/ "|" \___/ "|" \___/ "|" \___ \ ,|, / \ ,|, / \ ,|, / ,:" ":, ,:" ":, ,:" ":, |" \___/ "|" \___/ "|" \___/ "|" |, / \ ,|, / \ ,|, / \ ,|, ":, ,:" ":, ,:" ":, ,:" __/ "|" \___/ "|" \___/ "|" \___ \ ,|, / \ ,|, / \ ,|, / ,:" ":, ,:" ":, ,:" ":, |" \___/ "|" \___/ "|" \___/ "|" |, / \ ,|, / \ ,|, / \ ,|, ":, ,:" ":, ,:" ":, ,:" __/ "|" \___/ "|" \___/ "|" \___ \ ,|, / \ ,|, / \ ,|, / ,:" ":, ,:" ":, ,:" ":, |" \___/ "|" \___/ "|" \___/ "|" |, / \ ,|, / \ ,|, / \ ,|, ":, ,:" ":, ,:" ":, ,:" __/ "|" \___/ "|" \___/ "|" \___ in this diagram, suppose that the ring of 10 dodecahedra is running vertically inside its sheath of 50 dodecahedra, whose exposed walls appear as irregular pentagons. then the horizontal @{edge->?}s are at the tops of the bumps in the surface, while the vertical @{edge->?}s are at the bottoms of the hollows. thus, the fat torus of 60 dodecahedra is covered with 10 rows of squat hexagons, with 5 hexagons in each row. similarly, this pattern is overlaid with 10 columns of tall hexagons, with 5 hexagons in each column. together, these overlaid patterns show that the two fat 60-cell tori can indeed be fit together, wall-to-wall and bump-into-hollow. while every @{edge->?} in the 600-cell is part of exactly one decagon, every dodecahedron in the 120-cell is part of 6 different 10-cell ring. the 120-cell can be parti- tioned into 12 @{link->?}ed rings, @placewise nearly parallel, so that the rings again trace the circles of the Hopf fibration. there 12 ways to perform this Hopf-like partition of the 120-cell. these 12 arrangements of rings correspond exactly to the 12 Hopf-like arrange- ments of decagons in the 600-cell. - don davis, boston *************************************************************/ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/BuildRefinement.c #define PROG_NAME "BuildRefinement" #define PROG_DESC "???" #define PROG_VERS "1.0" #define BuildRefinement_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This module builds a refinement of a triangulation $T$ exchanging each single tetrahedron of $T$ by a $K$-refined tetrahedron as created by the "Refine" procedure on the library "libm3subi". */ #include #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE #include TYPE typedef struct Options_t { char *inFileTp; /* Input file name (minus extensions) */ char *inFileSt; /* Input file name (minus extensions) */ char *outFile; /* Output file name prefix */ uint order; /* order of the refinement */ bool_t detail; /* print some detail information */ bool_t fixed; /* retain the previus geometry */ bool_t net; /* drawing each existing wall as a net with small spheres and thin cylinders */ } double Corner = ARRAY [0..23] OF Place_t; double Report = RECORD bool_t bo; INTEGER tu[1+1]; } @PLACE == Place_vec_t; double CENTER = Node_vec_t; PROCEDURE MyAssert(*p: r4_t) { assert(!( (p[0] == 0.0) AND (p[1] == 0.0) AND (p[2] == 0.0) AND (p[3] == 0.0) ) ); } /* END MyAssert */ bool_t AreGlued(Place_t @p, Place_t b) /* This procedure return TRUE iff the corners (@places) "a" e "b" are glued in the original triangulation $T$; otherwise return FALSE. */ bool_t CellsInfo() /* First step: We need to compare the cells information. */ { if (((Ppos(a) == Pneg(b))) && ((Ppos(b) == Pneg(a)))) { return TRUE; } else { return FALSE } } CellsInfo; bool_t NodesInfo() /* Second step: We need to compare the nodes information. */ { if (((OrgV(a) == OrgV(b)) AND (OrgV(NextE(a)) == OrgV(NextE(b))) AND (OrgV(PrevE(a)) == OrgV(PrevE(b))))){ return TRUE; } else { return FALSE } } NodesInfo; { if ((CellsInfo())){ if ((NodesInfo())) { assert(a == Spin(b)) && (b == Spin(a)); return TRUE; } } return FALSE; } /* END AreGlued */ Node MidOcta(Place_t @p) /* Return a node that is the medial node of an triangulated octahedron. This node has a "VP" label as type. */ { Node_t v = OrgV(PrevE(PrevF(PrevF(a)))); { v.label = "VP"; return v; } } /* END MidOcta */ Node InterNode(Place_t @p) /* Return a node that is a internal to the macro-tetrahedron. This node is located on a @{edge->?} and wall and present only in order greater than four. This node has a "VP" label as type. */ { Node_t v = OrgV(PrevE(PrevF(a))); { v.label = "FE"; return v; } } /* END InterNode */ Report AreGluedCorners(*ca,cb: Corner) /* This procedure return TRUE iff the tetrahedra with corners "ca" and "cb" must be glued. */ Report *re; { for (i = 0; i <= (23); i++){ for (j = 0; j <= (23); j++) { if ((AreGlued(ca.e[i],cb.e[j]))) { re.bo = TRUE; re.tu[0] = i; re.tu[1] = j; } } } return re; } /* END AreGluedCorners */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) VAR ElemTableRec_t newtop; vme : REF ARRAY OF CENTER; /* Array of mid node of octahedra */ vin : REF ARRAY OF CENTER; /* An array of internal node */ nvv,nve,nvf,nvp,nfe: uint = 0; /* numbers nodes of each type */ nov,noe,nof,nop : uint = 0; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? co = NEW(REF ARRAY OF Corner, top->cell.ne); ??? nco = NEW(REF ARRAY OF Refine.Corner, top->cell.ne); ??? rc = Triangulation.ReadState(o->inFileSt), ??? c = rc^ { /* Assertion */ if (top->der!=3) { fprintf(stderr,"\nThis topology isn't a triangulation\n"); Process.Exit¦(1); } fprintf(stderr,"\n" & Fmt.Int(o->order) & "-Refining from: " & o->inFileTp & ".tp\n"); /* compute Corners table */ for (i = 0; i < top->cell.ne; i++) { ??? da = Srot(top.cell[i]); Place_t pa = Tors(da); { co.e[i] = BuildCornerTable(pa); nco.e[i] = SubdivideTetrahedron(o->order, pa, o->net, top); } if (o->detail) { fprintf(stderr, "tetrahedron " & Fmt.Int(i) & ":\n"); PrintCornerTable(co.e[i]); } } /* save memory for the medial and internal nodes .*/ if (o->order == 1) { vme = NEW(REF ARRAY OF CENTER, top->cell.ne, 0); } else if (o->order == 2){ vme = NEW(REF ARRAY OF CENTER, top->cell.ne, 1); } else if (o->order == 3){ vme = NEW(REF ARRAY OF CENTER, top->cell.ne, 4); } else if (o->order == 4){ vme = NEW(REF ARRAY OF CENTER, top->cell.ne, 10); vin = NEW(REF ARRAY OF CENTER, top->cell.ne, 1); } else if (o->order == 5){ vme = NEW(REF ARRAY OF CENTER, top->cell.ne, 20); vin = NEW(REF ARRAY OF CENTER, top->cell.ne, 4); } for (i = 0; i < top->cell.ne; i++) { if (o->order == 2) { vme[i][0] = MidOcta(nco.e[i].front[0]); } else if (o->order == 3){ vme[i][ 0] = MidOcta(nco.e[i].front[ 0]); vme[i][ 1] = MidOcta(nco.e[i].front[ 1]); vme[i][ 2] = MidOcta(nco.e[i].front[ 3]); vme[i][ 3] = MidOcta(nco.e[i].back [ 0]); } else if (o->order == 4){ vme[i][ 0] = MidOcta(nco.e[i].front[ 0]); vme[i][ 1] = MidOcta(nco.e[i].front[ 1]); vme[i][ 2] = MidOcta(nco.e[i].front[ 3]); vme[i][ 3] = MidOcta(nco.e[i].front[ 4]); vme[i][ 4] = MidOcta(nco.e[i].front[ 6]); vme[i][ 5] = MidOcta(nco.e[i].front[ 8]); vme[i][ 6] = MidOcta(nco.e[i].back [ 0]); vme[i][ 7] = MidOcta(nco.e[i].right[ 6]); vme[i][ 8] = MidOcta(nco.e[i].right[13]); vme[i][ 9] = MidOcta(nco.e[i].left [13]); /* */ vin[i][ 0] = InterNode(nco.e[i].front[6]); } else if (o->order == 5){ vme[i][ 0] = MidOcta(nco.e[i].front[ 0]); vme[i][ 1] = MidOcta(nco.e[i].front[ 1]); vme[i][ 2] = MidOcta(nco.e[i].front[ 3]); vme[i][ 3] = MidOcta(nco.e[i].front[ 4]); vme[i][ 4] = MidOcta(nco.e[i].front[ 6]); vme[i][ 5] = MidOcta(nco.e[i].front[ 8]); vme[i][ 6] = MidOcta(nco.e[i].front[ 9]); vme[i][ 7] = MidOcta(nco.e[i].front[11]); vme[i][ 8] = MidOcta(nco.e[i].front[13]); vme[i][ 9] = MidOcta(nco.e[i].front[15]); vme[i][10] = MidOcta(nco.e[i].back [ 0]); vme[i][11] = MidOcta(nco.e[i].right[11]); vme[i][12] = MidOcta(nco.e[i].right[20]); vme[i][13] = MidOcta(nco.e[i].right[ 6]); vme[i][14] = MidOcta(nco.e[i].right[13]); vme[i][15] = MidOcta(nco.e[i].right[22]); vme[i][16] = MidOcta(nco.e[i].left [20]); vme[i][17] = MidOcta(nco.e[i].left [13]); vme[i][18] = MidOcta(nco.e[i].left [22]); vme[i][19] = MidOcta(nco.e[i].back [ 6]); /* */ vin[i][ 0] = InterNode(nco.e[i].front[ 6]); vin[i][ 1] = InterNode(nco.e[i].front[11]); vin[i][ 2] = InterNode(nco.e[i].front[13]); vin[i][ 3] = InterNode(nco.e[i].right[11]); } } /* compute that corners that must be glued */ for (k = 0; k < top->wall.ne; k++) { ??? f = top->wall[k].pa; ??? i = Triangulation.Ppos(f)->num; ??? j = Triangulation.Pneg(f)->num; { if (((Triangulation.Ppos(f)!=NULL)) && ((Triangulation.Pneg(f)!=NULL))) { ??? re = AreGluedCorners(co.e[i],co.e[j]); { if (re.bo) { if (o->detail) { fprintf(stderr, "New Corners that must be glue :" \ " NC[" & Pad(Int(i),3) &"," & Pad(Int(re.tu[0]),3)&"] and" \ " NC[" & Pad(Int(j),3) &"," & Pad(Int(re.tu[1]),3)&"]\n"); } ??? ar = Refine.Place_tsOnFrontier(nco.e[i],re.tu[0], o->order); double br = Refine.Place_tsOnFrontier(nco.e[j], re.tu[1], o->order) { GlueMacroTetrahedra(ar,br); } } } } } } for (i = 0; i < top->node.ne; i++) { ??? v = NARROW(top->node[i], Node); { double vl = v.label ){ if (( Text.Equal(vl,"VV"))){ nov++; } else if (0 == strcmp(vl,"VE"))){ noe++; } else if (0 == strcmp(vl,"VF"))){ nof++; } else if (0 == strcmp(vl,"VP"))){ nop++; } } } newtop = MakeElemTable(nco.e[0].right[0],1); for (i = 0; i < newtop.node.ne; i++) { ??? v = NARROW(newtop.node[i], Node); { double vl = v.label ){ if (( Text.Equal(vl,"VV"))){ nvv++; } else if (0 == strcmp(vl,"VE"))){ nve++; } else if (0 == strcmp(vl,"VF"))){ nvf++; } else if (0 == strcmp(vl,"VP"))){ nvp++; } else if (0 == strcmp(vl,"FE"))){ nfe++; } } } assert(newtop.node.ne == nvv + nve + nvf + nvp + nfe); assert(nvv == nov); if (o->order >= 2) { assert(nve == top->NE * (o->order-1) + noe); } if ( o->order == 3){ assert(nvf == top->wall.ne * 1 + nof); } else if (o->order == 4){ assert(nvf == top->wall.ne * 3 + nof); } else if (o->order == 5){ assert(nvf == top->wall.ne * 6 + nof); } /* useful assertion */ ??? o1 = o->order; ??? o2 = o1*o1; ??? o3 = o2*o1; ??? cte = (5*o3-2*o1) DIV 3; { assert(newtop.cell.ne == top->cell.ne * cte); if ( o->order == 1){ assert(nvp == top->cell.ne * 0 + nop); } else if (o->order == 2){ assert(nvp == top->cell.ne * 1 + nop); } else if (o->order == 3){ assert(nvp == top->cell.ne * 4 + nop); } else if (o->order == 4 ){ assert(nvp == top->cell.ne * 10 + nop); assert(nfe == top->cell.ne * 1); } else if (o->order == 5 ){ assert(nvp == top->cell.ne * 20 + nop); assert(nfe == top->cell.ne * 4); } } ??? com = Fmt.Int(o->order) & "-Refined from: " & o->inFileTp & ".tp\n" & "Created by BuildRefinement: " & o->outFile & ".tp"; ??? ncord = SettingCoords(top,newtop,c,co,nco,o->order,vme,vin,o->net); double rcord = GenCoords(newtop)^; { WriteTopology (o->outFile, newtop, com); /*WriteTable (o->outFile, newtop, com);*/ WriteMaterials(o->outFile, newtop, com); if (o->fixed) { for (i = 0 TO LAST(ncord^)-1) { ncord[i] = r4_Scale(((double)1.0), ncord[i]); } WriteState(o->outFile&"-Fix",newtop,ncord^,com&": Fixed Geometry\n"); } else { WriteState(o->outFile, newtop, rcord, com & ": Random Geometry\n"); } } } } /* END DoIt */ Corner BuildCornerTable(Place_t @p) /* This procedure builds an array of 24 wedge @places, such all elements on the array have the same negative cell "Pneg". The @place "a" in the argument must be a @place that represent one tetrahe- dron of $T$ (in the primal space). */ Corner *c; { ??? a0 = a; Place_t a1 = NextE(a0); Place_t a2 = NextE(a1); Place_t b0 = Spin(PrevF(a0)); Place_t c0 = Spin(PrevF(a1)); Place_t d0 = Spin(PrevF(a2)); { /* the 24 elements on the array must have the same negative cell. */ c[0 ] = a0; c[1 ] = NextE(a0); c[2 ] = PrevE(a0); c[3 ] = b0; c[4 ] = NextE(b0); c[5 ] = PrevE(b0); c[6 ] = c0; c[7 ] = NextE(c0); c[8 ] = PrevE(c0); c[9 ] = d0; c[10] = NextE(d0); c[11] = PrevE(d0); assert(c[0] == a); /* basically the last 12 @places in the "corner" array are the "spined- clocked" version of the firsts 12 places. */ for (j = 1; j <= (12); j++) { c[j+11] = Clock(Spin(c[j-1])); } /* for assert that the 24 @places wedge have the same negative cell. */ for (m = 0; m <= (23); m++) { for (n = m+1; n <= (23); n++) { assert(Pneg(c[m]) == Pneg(c[n])); } } } return c; } /* END BuildCornerTable */ PROCEDURE PrintCornerTable(*ac : Corner) /* Prints detail information about the macro-tetrahedra that must be glued. */ { for (j = 0; j < 12; j++){ fprintf(stderr,Fmt.Pad(Fmt.Int(j),6) & " "); } fprintf(stderr,"\n--------------------------------------------------" \ "---------------------------------------\n"); for (j = 0; j < 12; j++) { Octf.PrintPlace(stderr, ac[j], 3, FALSE); } fprintf(stderr, "\ng\n"); for (j = 12; j <= (23); j++) { fprintf(stderr,Fmt.Pad(Fmt.Int(j),6) & " "); } fprintf(stderr,"\n--------------------------------------------------" \ "---------------------------------------\n"); for (j = 12; j <= (23); j++) { Octf.PrintPlace(stderr, ac[j], 3, FALSE); } fprintf(stderr, "\n\n"); } /* END PrintCornerTable */ Refine.Corner SubdivideTetrahedron( uint order; Place_t @p; bool_t net; ElemTableRec_t *top) /* This procedure rescues the propiertes of the nodes, @{edge->?}s and walls belonging to the original tetrahedron represented by the @place "a", and expands this propiertes to the macro-tetrahedron. */ void InheritNodes(v,V: Node) /* Inherits node propiertes.*/ { V->exists = v->exists; V.fixed = v.fixed; V.color = v.color; V.transp = v.transp; V.radius = v.radius; V.label = v.label; } InheritNodes; PROCEDURE Inherit@{Edge->?}s(e,E: @{Edge->?}) == /* Inherits @{edge->?} propiertes.*/ { ??? ed = top.edge[e->num]; { E->exists = ed->exists; E.color = ed.color; E.transp = ed.transp; E.radius = ed.radius; E->root = ed->root; } } Inherit@{Edge->?}s; void InheritWalls(f,F: Wall) /* Inherits wall propiertes.*/ { ??? fd = top.wall[f->num]; { F->exists = fd->exists; F.color = fd.color; F.transp = fd.transp; F->root = fd->root; } } InheritWalls; co : Refine.Corner; { if ( order == 1){ co = MakeTetra(1,net); } else if (order == 2){ co = MakeTetra(2,net); } else if (order == 3){ co = MakeTetra(3,net); } else if (order == 4){ co = MakeTetra(4,net); } else if (order == 5){ co = MakeTetra(5,net); } else { fprintf(stderr,"BuildRefinement: Order must be less equal to 5\n"); assert(order <= 5); } ??? o2 = order*order; ??? ve = Triangulation.TetraNegNodes(a); ??? ed = Triangulation.TetraEdges(a); ??? fa = Triangulation.TetraWalls(a); ??? v0 = ve[0]; ??? v1 = ve[1]; ??? v2 = ve[2]; ??? v3 = ve[3]; ??? e0 = ed[0]; ??? e1 = ed[1]; ??? e2 = ed[2]; ??? e3 = ed[3]; ??? e4 = ed[4]; ??? e5 = ed[5]; ??? f0 = fa[0]; ??? f1 = fa[1]; ??? f2 = fa[2]; ??? f3 = fa[3]; Node_t V0 = OrgV(PrevE(co.back [0])); ??? V1 = OrgV(PrevE(co.front[0])); ??? V2 = OrgV(NextE (co.front[o2-1])); ??? V3 = OrgV(PrevE(co.left [o2-1])); { /* nodes */ InheritNodes(v0,V0); InheritNodes(v1,V1); InheritNodes(v2,V2); InheritNodes(v3,V3); /* walls */ for (i = 0; i < o2; i++) { InheritWalls(f0, PWedge(co.right[i]).wall); InheritWalls(f1, PWedge(co.left [i]).wall); InheritWalls(f2, PWedge(co.front[i]).wall); InheritWalls(f3, PWedge(co.back [i]).wall); } if (net) { /* iff the wall not exists then non exists the elements on the net. */ ??? f0e = top.wall[f0->num]->exists; ??? f1e = top.wall[f1->num]->exists; ??? f2e = top.wall[f2->num]->exists; ??? f3e = top.wall[f3->num]->exists; { ModSetGrade(order,co,f0e,f1e,f2e,f3e); } } /* @{edge->?}s : e0 */ for (i = 1; i <= (order); i++) { Inherit@{Edge->?}s(e0, PWedge(co.right[(i-1)*(i-1)]).edge); } if (! top.edge[e0->num]->exists) { for (i = 1; i < order; i++) { OrgV(co.right[(i-1)*(i-1)])->exists = FALSE; } } ??? cor = top.edge[e0->num].color; { for (i = 1; i < order; i++) { OrgV(co.right[(i-1)*(i-1)]).color = cor; } } /* e1 */ for (i = 1; i <= (order); i++) { Inherit@{Edge->?}s(e1,PWedge( NextE(co.right[i*i-1])).edge); } if (! top.edge[e1->num]->exists) { for (i = 1; i < order; i++) { OrgV(PrevE(co.right[i*i-1]))->exists = FALSE; } } ??? cor = top.edge[e1->num].color; { for (i = 1; i < order; i++) { OrgV(PrevE(co.right[i*i-1])).color = cor; } } /* e3 */ for (i = 1; i <= (order); i++) { Inherit@{Edge->?}s(e3, PWedge(NextE(co.left[i*i-1])).edge); } if (! top.edge[e3->num]->exists) { for (i = 1; i < order; i++) { OrgV(PrevE(co.left[i*i-1]))->exists = FALSE; } } ??? cor = top.edge[e3->num].color; { for (i = 1; i < order; i++) { OrgV(PrevE(co.left[i*i-1])).color = cor; } } /* e4 */ for (i = 1; i <= (order); i++) { Inherit@{Edge->?}s(e4, PWedge(PrevE(co.back[(i-1)*(i-1)])).edge); } if (! top.edge[e4->num]->exists) { for (i = 1; i < order; i++) { OrgV(co.back[(i-1)*(i-1)])->exists = FALSE; } } ??? cor = top.edge[e4->num].color; { for (i = 1; i < order; i++) { OrgV(co.back[(i-1)*(i-1)]).color = cor; } } /* e2 */ for (i = 1; i <= (order); i++) { Inherit@{Edge->?}s(e2, PWedge(NextE(co.back[i*i-1])).edge); } if (! top.edge[e2->num]->exists) { for (i = 1; i < order; i++) { OrgV(NextE(co.back[i*i-1]))->exists = FALSE; } } ??? cor = top.edge[e2->num].color; { for (i = 1; i < order; i++) { OrgV(NextE(co.back[i*i-1])).color = cor; } } /* e5 */ INTEGER count = o2-1; VAR { Inherit@{Edge->?}s(e5, PWedge(co.front[count]).edge); for (j = 1; j < order; j++) { Inherit@{Edge->?}s(e5, PWedge(co.front[count-2]).edge); count = count-2; }; count = o2-1; if (! top.edge[e5->num]->exists) { for (j = 1; j < order; j++) { OrgV(co.front[count])->exists = FALSE; count = count-2; } }; count = o2-1; ??? cor = top.edge[e5->num].color; { for (j = 1; j < order; j++) { OrgV(co.front[count]).color = cor; count = count-2; } } } return co; } } /* END SubdivideTetrahedron */ PROCEDURE SettingCoords( ElemTableRec_t *oldtop; ElemTableRec_t *newtop; *oldco : Triangulation.Coords_t; *cor : REF ARRAY OF Corner; *ncor : REF ARRAY OF Refine.Corner; uint order; mocta : REF ARRAY OF CENTER; inter : REF ARRAY OF CENTER; bool_t net; ) : REF Triangulation.Coords_t == uint NewNumVer(Node_t v) /*Return the new number node of the node "v" on the "newtp" table.*/ VAR uint n = 0; { for (i = 0; i < newtp.NV; i++) { ??? w = newtp.node[i]; { if (w == v){ n = i; EXIT; } } } return n; } NewNumVer; bool_t PresentNode(Node_t v) /* Return TRUE iff the node "v" is present on the "newtp" table.*/ { for (i = 0; i < newtp.NV; i++) { ??? w = newtp.node[i]; { if (w == v){ return TRUE; }; } } return FALSE; } PresentNode; VAR newco : REF Triangulation.Coords_t; /* nodes */ v0,v1,v2,v3 : uint; /* @{edge->?}s */ e0 = NEW(REF uint_vec_t , order-1); e1 = NEW(REF uint_vec_t , order-1); e2 = NEW(REF uint_vec_t , order-1); e3 = NEW(REF uint_vec_t , order-1); e4 = NEW(REF uint_vec_t , order-1); e5 = NEW(REF uint_vec_t , order-1); /* walls */ f0 : REF uint_vec_t; f1 : REF uint_vec_t; f2 : REF uint_vec_t; f3 : REF uint_vec_t; { if (order == 3){ f0 = NEW(REF uint_vec_t , 1); f1 = NEW(REF uint_vec_t , 1); f2 = NEW(REF uint_vec_t , 1); f3 = NEW(REF uint_vec_t , 1); } else if (order == 4){ f0 = NEW(REF uint_vec_t , 3); f1 = NEW(REF uint_vec_t , 3); f2 = NEW(REF uint_vec_t , 3); f3 = NEW(REF uint_vec_t , 3); } else if (order == 5){ f0 = NEW(REF uint_vec_t , 6); f1 = NEW(REF uint_vec_t , 6); f2 = NEW(REF uint_vec_t , 6); f3 = NEW(REF uint_vec_t , 6); } newco = NEW(REF Triangulation.Coords_t, newtp.NV); /* original nodes */ for (i = 0; i < oldtp.NP; i++) { ??? o2 = order*order; Node_t V0 = OrgV(PrevE(ncor[i].back [0])); ??? V1 = OrgV(PrevE(ncor[i].front[0])); ??? V2 = OrgV(NextE (ncor[i].front[o2-1])); ??? V3 = OrgV(PrevE(ncor[i].left [o2-1])); { v0 = OrgV(cor[i,0])->num; v1 = OrgV(cor[i,1])->num; v2 = OrgV(cor[i,2])->num; v3 = OrgV(cor[i,5])->num; if ((PresentNode(V0))) { newco.e[NewNumVer(V0)] = oldco.e[v0]; } if ((PresentNode(V1))) { newco.e[NewNumVer(V1)] = oldco.e[v1]; } if ((PresentNode(V2))) { newco.e[NewNumVer(V2)] = oldco.e[v2]; } if ((PresentNode(V3))) { newco.e[NewNumVer(V3)] = oldco.e[v3]; } } /* nodes on the subdivided @{edge->?}s */ /* e0 : tips nodes V0 and v1 */ ??? dx = (oldco.e[v1][0] - oldco.e[v0][0])/((double)order); ??? dy = (oldco.e[v1][1] - oldco.e[v0][1])/((double)order); ??? dz = (oldco.e[v1][2] - oldco.e[v0][2])/((double)order); ??? dw = (oldco.e[v1][3] - oldco.e[v0][3])/((double)order); { for (j = 1; j < order; j++) { Node_t ve = OrgV(ncor[i].right[(j-1)*(j-1)]); { if ((PresentNode(ve))) { e0[j-1] = NewNumVer(ve); newco.e[e0[j-1]][0] = oldco.e[v1][0] - ((double)j) * dx; newco.e[e0[j-1]][1] = oldco.e[v1][1] - ((double)j) * dy; newco.e[e0[j-1]][2] = oldco.e[v1][2] - ((double)j) * dz; newco.e[e0[j-1]][3] = oldco.e[v1][3] - ((double)j) * dw; } } } } /* end e0 @{edge->?} */ /* e1 : tips nodes V1 and v2 */ ??? dx = (oldco.e[v1][0] - oldco.e[v2][0])/((double)order); ??? dy = (oldco.e[v1][1] - oldco.e[v2][1])/((double)order); ??? dz = (oldco.e[v1][2] - oldco.e[v2][2])/((double)order); ??? dw = (oldco.e[v1][3] - oldco.e[v2][3])/((double)order); { for (j = 1; j < order; j++) { Node_t ve = OrgV(PrevE(ncor[i].right[j*j-1])); { if ((PresentNode(ve))) { e1[j-1] = NewNumVer(ve); newco.e[e1[j-1]][0] = oldco.e[v1][0] - ((double)j) * dx; newco.e[e1[j-1]][1] = oldco.e[v1][1] - ((double)j) * dy; newco.e[e1[j-1]][2] = oldco.e[v1][2] - ((double)j) * dz; newco.e[e1[j-1]][3] = oldco.e[v1][3] - ((double)j) * dw; } } } } /* end e1 @{edge->?} */ /* e3 : tips nodes V1 and v3 */ ??? dx = (oldco.e[v1][0] - oldco.e[v3][0])/((double)order); ??? dy = (oldco.e[v1][1] - oldco.e[v3][1])/((double)order); ??? dz = (oldco.e[v1][2] - oldco.e[v3][2])/((double)order); ??? dw = (oldco.e[v1][3] - oldco.e[v3][3])/((double)order); { for (j = 1; j < order; j++) { Node_t ve = OrgV(PrevE(ncor[i].left[j*j-1])); { if ((PresentNode(ve))) { e3[j-1] = NewNumVer(ve); newco.e[e3[j-1]][0] = oldco.e[v1][0] - ((double)j) * dx; newco.e[e3[j-1]][1] = oldco.e[v1][1] - ((double)j) * dy; newco.e[e3[j-1]][2] = oldco.e[v1][2] - ((double)j) * dz; newco.e[e3[j-1]][3] = oldco.e[v1][3] - ((double)j) * dw; } } } } /* end e3 @{edge->?} */ /* e4 : tips nodes V0 and v3 */ ??? dx = (oldco.e[v0][0] - oldco.e[v3][0])/((double)order); ??? dy = (oldco.e[v0][1] - oldco.e[v3][1])/((double)order); ??? dz = (oldco.e[v0][2] - oldco.e[v3][2])/((double)order); ??? dw = (oldco.e[v0][3] - oldco.e[v3][3])/((double)order); { for (j = 1; j < order; j++) { Node_t ve = OrgV(ncor[i].back[(j-1)*(j-1)]); { if ((PresentNode(ve))) { e4[j-1] = NewNumVer(ve); newco.e[e4[j-1]][0] = oldco.e[v0][0] - ((double)j) * dx; newco.e[e4[j-1]][1] = oldco.e[v0][1] - ((double)j) * dy; newco.e[e4[j-1]][2] = oldco.e[v0][2] - ((double)j) * dz; newco.e[e4[j-1]][3] = oldco.e[v0][3] - ((double)j) * dw; } } } } /* end e4 @{edge->?} */ /* e2 : tips nodes V0 and v2 */ ??? dx = (oldco.e[v0][0] - oldco.e[v2][0])/((double)order); ??? dy = (oldco.e[v0][1] - oldco.e[v2][1])/((double)order); ??? dz = (oldco.e[v0][2] - oldco.e[v2][2])/((double)order); ??? dw = (oldco.e[v0][3] - oldco.e[v2][3])/((double)order); { for (j = 1; j < order; j++) { Node_t ve = OrgV(NextE(ncor[i].back[j*j-1])); { if ((PresentNode(ve))) { e2[j-1] = NewNumVer(ve); newco.e[e2[j-1]][0] = oldco.e[v0][0] - ((double)j) * dx; newco.e[e2[j-1]][1] = oldco.e[v0][1] - ((double)j) * dy; newco.e[e2[j-1]][2] = oldco.e[v0][2] - ((double)j) * dz; newco.e[e2[j-1]][3] = oldco.e[v0][3] - ((double)j) * dw; } } } } /* end e2 @{edge->?} */ /* e5 : tips nodes V2 and v3 */ ??? dx = (oldco.e[v2][0] - oldco.e[v3][0])/((double)order); ??? dy = (oldco.e[v2][1] - oldco.e[v3][1])/((double)order); ??? dz = (oldco.e[v2][2] - oldco.e[v3][2])/((double)order); ??? dw = (oldco.e[v2][3] - oldco.e[v3][3])/((double)order); { VAR uint count; { count = order*order-1; for (j = 1; j < order; j++) { Node_t ve = OrgV(ncor[i].front[count]); { count = count-2; if ((PresentNode(ve))) { e5[j-1] = NewNumVer(ve); newco.e[e5[j-1]][0] = oldco.e[v2][0] - ((double)j) * dx; newco.e[e5[j-1]][1] = oldco.e[v2][1] - ((double)j) * dy; newco.e[e5[j-1]][2] = oldco.e[v2][2] - ((double)j) * dz; newco.e[e5[j-1]][3] = oldco.e[v2][3] - ((double)j) * dw; } } } } } /* end e5 @{edge->?} */ /* nodes on the triangulated wall. */ if (order == 3) { Node_t F0 = OrgV(ncor[i].right[3]); ??? F1 = OrgV(ncor[i].left [3]); ??? F3 = OrgV(ncor[i].back [3]); ??? F2 = OrgV(ncor[i].front[3]); { ??? dx = (newco.e[e1[0]][0] + newco.e[e2[0]][0])/2.0; ??? dy = (newco.e[e1[0]][1] + newco.e[e2[0]][1])/2.0; ??? dz = (newco.e[e1[0]][2] + newco.e[e2[0]][2])/2.0; ??? dw = (newco.e[e1[0]][3] + newco.e[e2[0]][3])/2.0; { if ((PresentNode(F0))) { if (! net){ assert(! F0->exists); } f0[0] = NewNumVer(F0); newco.e[f0[0]][0] = dx; newco.e[f0[0]][1] = dy; newco.e[f0[0]][2] = dz; newco.e[f0[0]][3] = dw; } } ??? dx = (newco.e[e0[0]][0] + newco.e[e4[1]][0])/((double)order-1); ??? dy = (newco.e[e0[0]][1] + newco.e[e4[1]][1])/((double)order-1); ??? dz = (newco.e[e0[0]][2] + newco.e[e4[1]][2])/((double)order-1); ??? dw = (newco.e[e0[0]][3] + newco.e[e4[1]][3])/((double)order-1); { if ((PresentNode(F1))) { if (! net){ assert(! F1->exists); } f1[0] = NewNumVer(F1); newco.e[f1[0]][0] = dx; newco.e[f1[0]][1] = dy; newco.e[f1[0]][2] = dz; newco.e[f1[0]][3] = dw; } } ??? dx = (newco.e[e3[0]][0] + newco.e[e5[0]][0])/((double)order-1); ??? dy = (newco.e[e3[0]][1] + newco.e[e5[0]][1])/((double)order-1); ??? dz = (newco.e[e3[0]][2] + newco.e[e5[0]][2])/((double)order-1); ??? dw = (newco.e[e3[0]][3] + newco.e[e5[0]][3])/((double)order-1); { if ((PresentNode(F2))) { if (! net){ assert(! F2->exists); } f2[0] = NewNumVer(F2); newco.e[f2[0]][0] = dx; newco.e[f2[0]][1] = dy; newco.e[f2[0]][2] = dz; newco.e[f2[0]][3] = dw; } } ??? dx = (newco.e[e4[0]][0] + newco.e[e5[0]][0])/((double)order-1); ??? dy = (newco.e[e4[0]][1] + newco.e[e5[0]][1])/((double)order-1); ??? dz = (newco.e[e4[0]][2] + newco.e[e5[0]][2])/((double)order-1); ??? dw = (newco.e[e4[0]][3] + newco.e[e5[0]][3])/((double)order-1); { if ((PresentNode(F3))) { if (! net){ assert(! F3->exists); } f3[0] = NewNumVer(F3); newco.e[f3[0]][0] = dx; newco.e[f3[0]][1] = dy; newco.e[f3[0]][2] = dz; newco.e[f3[0]][3] = dw; } } } } else if (order == 4){ Node_t F00 = OrgV(ncor[i].right[3]); ??? F01 = OrgV(ncor[i].right[8]); ??? F02 = OrgV(ncor[i].right[6]); ??? F10 = OrgV(ncor[i].left[3]); ??? F11 = OrgV(ncor[i].left[8]); ??? F12 = OrgV(ncor[i].left[6]); ??? F30 = OrgV(ncor[i].back[3]); ??? F31 = OrgV(ncor[i].back[8]); ??? F32 = OrgV(ncor[i].back[6]); ??? F20 = OrgV(ncor[i].front[3]); ??? F21 = OrgV(ncor[i].front[8]); ??? F22 = OrgV(ncor[i].front[6]); { assert0 == strcmp(F00.label,"VF")); assert0 == strcmp(F01.label,"VF")); assert0 == strcmp(F02.label,"VF")); assert0 == strcmp(F10.label,"VF")); assert0 == strcmp(F11.label,"VF")); assert0 == strcmp(F12.label,"VF")); assert0 == strcmp(F30.label,"VF")); assert0 == strcmp(F31.label,"VF")); assert0 == strcmp(F32.label,"VF")); assert0 == strcmp(F20.label,"VF")); assert0 == strcmp(F21.label,"VF")); assert0 == strcmp(F22.label,"VF")); /* Right */ ??? dx = (newco.e[e1[0]][0] - newco.e[e2[0]][0])/((double)order-1); ??? dy = (newco.e[e1[0]][1] - newco.e[e2[0]][1])/((double)order-1); ??? dz = (newco.e[e1[0]][2] - newco.e[e2[0]][2])/((double)order-1); ??? dw = (newco.e[e1[0]][3] - newco.e[e2[0]][3])/((double)order-1); { if ((PresentNode(F00))) { if (! net){ assert(! F00->exists); } f0[0] = NewNumVer(F00); newco.e[f0[0]][0] = newco.e[e1[0]][0] - 1.0 * dx; newco.e[f0[0]][1] = newco.e[e1[0]][1] - 1.0 * dy; newco.e[f0[0]][2] = newco.e[e1[0]][2] - 1.0 * dz; newco.e[f0[0]][3] = newco.e[e1[0]][3] - 1.0 * dw; } if ((PresentNode(F02))) { if (! net){ assert(! F02->exists); } f0[2] = NewNumVer(F02); newco.e[f0[2]][0] = newco.e[e1[0]][0] - 2.0 * dx; newco.e[f0[2]][1] = newco.e[e1[0]][1] - 2.0 * dy; newco.e[f0[2]][2] = newco.e[e1[0]][2] - 2.0 * dz; newco.e[f0[2]][3] = newco.e[e1[0]][3] - 2.0 * dw; } } ??? dx = (newco.e[e1[1]][0] - newco.e[e2[1]][0])/((double)order-2); ??? dy = (newco.e[e1[1]][1] - newco.e[e2[1]][1])/((double)order-2); ??? dz = (newco.e[e1[1]][2] - newco.e[e2[1]][2])/((double)order-2); ??? dw = (newco.e[e1[1]][3] - newco.e[e2[1]][3])/((double)order-2); { if ((PresentNode(F01))) { if (! net){ assert(! F01->exists); } f0[1] = NewNumVer(F01); newco.e[f0[1]][0] = newco.e[e1[1]][0] - 1.0 * dx; newco.e[f0[1]][1] = newco.e[e1[1]][1] - 1.0 * dy; newco.e[f0[1]][2] = newco.e[e1[1]][2] - 1.0 * dz; newco.e[f0[1]][3] = newco.e[e1[1]][3] - 1.0 * dw; } } /* Left */ ??? dx = (newco.e[e0[0]][0] - newco.e[e4[2]][0])/((double)order-1); ??? dy = (newco.e[e0[0]][1] - newco.e[e4[2]][1])/((double)order-1); ??? dz = (newco.e[e0[0]][2] - newco.e[e4[2]][2])/((double)order-1); ??? dw = (newco.e[e0[0]][3] - newco.e[e4[2]][3])/((double)order-1); { if ((PresentNode(F10))) { if (! net){ assert(! F10->exists); } f1[0] = NewNumVer(F10); newco.e[f1[0]][0] = newco.e[e0[0]][0] - 1.0 * dx; newco.e[f1[0]][1] = newco.e[e0[0]][1] - 1.0 * dy; newco.e[f1[0]][2] = newco.e[e0[0]][2] - 1.0 * dz; newco.e[f1[0]][3] = newco.e[e0[0]][3] - 1.0 * dw; } if ((PresentNode(F11))) { if (! net){ assert(! F11->exists); } f1[1] = NewNumVer(F11); newco.e[f1[1]][0] = newco.e[e0[0]][0] - 2.0 * dx; newco.e[f1[1]][1] = newco.e[e0[0]][1] - 2.0 * dy; newco.e[f1[1]][2] = newco.e[e0[0]][2] - 2.0 * dz; newco.e[f1[1]][3] = newco.e[e0[0]][3] - 2.0 * dw; } } ??? dx = (newco.e[e0[1]][0] - newco.e[e4[1]][0])/((double)order-2); ??? dy = (newco.e[e0[1]][1] - newco.e[e4[1]][1])/((double)order-2); ??? dz = (newco.e[e0[1]][2] - newco.e[e4[1]][2])/((double)order-2); ??? dw = (newco.e[e0[1]][3] - newco.e[e4[1]][3])/((double)order-2); { if ((PresentNode(F12))) { if (! net){ assert(! F12->exists); } f1[2] = NewNumVer(F12); newco.e[f1[2]][0] = newco.e[e0[1]][0] - 1.0 * dx; newco.e[f1[2]][1] = newco.e[e0[1]][1] - 1.0 * dy; newco.e[f1[2]][2] = newco.e[e0[1]][2] - 1.0 * dz; newco.e[f1[2]][3] = newco.e[e0[1]][3] - 1.0 * dw; } } /* Front */ ??? dx = (newco.e[e3[0]][0] - newco.e[e5[0]][0])/((double)order-1); ??? dy = (newco.e[e3[0]][1] - newco.e[e5[0]][1])/((double)order-1); ??? dz = (newco.e[e3[0]][2] - newco.e[e5[0]][2])/((double)order-1); ??? dw = (newco.e[e3[0]][3] - newco.e[e5[0]][3])/((double)order-1); { if ((PresentNode(F20))) { if (! net){ assert(! F20->exists); } f2[0] = NewNumVer(F20); newco.e[f2[0]][0] = newco.e[e3[0]][0] - 1.0 * dx; newco.e[f2[0]][1] = newco.e[e3[0]][1] - 1.0 * dy; newco.e[f2[0]][2] = newco.e[e3[0]][2] - 1.0 * dz; newco.e[f2[0]][3] = newco.e[e3[0]][3] - 1.0 * dw; } if ((PresentNode(F21))) { if (! net){ assert(! F21->exists); } f2[1] = NewNumVer(F21); newco.e[f2[1]][0] = newco.e[e3[0]][0] - 2.0 * dx; newco.e[f2[1]][1] = newco.e[e3[0]][1] - 2.0 * dy; newco.e[f2[1]][2] = newco.e[e3[0]][2] - 2.0 * dz; newco.e[f2[1]][3] = newco.e[e3[0]][3] - 2.0 * dw; } } ??? dx = (newco.e[e3[1]][0] - newco.e[e5[1]][0])/((double)order-2); ??? dy = (newco.e[e3[1]][1] - newco.e[e5[1]][1])/((double)order-2); ??? dz = (newco.e[e3[1]][2] - newco.e[e5[1]][2])/((double)order-2); ??? dw = (newco.e[e3[1]][3] - newco.e[e5[1]][3])/((double)order-2); { if ((PresentNode(F22))) { if (! net){ assert(! F22->exists); } f2[2] = NewNumVer(F22); newco.e[f2[2]][0] = newco.e[e3[1]][0] - 1.0 * dx; newco.e[f2[2]][1] = newco.e[e3[1]][1] - 1.0 * dy; newco.e[f2[2]][2] = newco.e[e3[1]][2] - 1.0 * dz; newco.e[f2[2]][3] = newco.e[e3[1]][3] - 1.0 * dw; } } /* Back */ ??? dx = (newco.e[e4[0]][0] - newco.e[e5[0]][0])/((double)order-1); ??? dy = (newco.e[e4[0]][1] - newco.e[e5[0]][1])/((double)order-1); ??? dz = (newco.e[e4[0]][2] - newco.e[e5[0]][2])/((double)order-1); ??? dw = (newco.e[e4[0]][3] - newco.e[e5[0]][3])/((double)order-1); { if ((PresentNode(F30))) { if (! net){ assert(! F30->exists); } f3[0] = NewNumVer(F30); newco.e[f3[0]][0] = newco.e[e4[0]][0] - 1.0 * dx; newco.e[f3[0]][1] = newco.e[e4[0]][1] - 1.0 * dy; newco.e[f3[0]][2] = newco.e[e4[0]][2] - 1.0 * dz; newco.e[f3[0]][3] = newco.e[e4[0]][3] - 1.0 * dw; } if ((PresentNode(F31))) { if (! net){ assert(! F31->exists); } f3[1] = NewNumVer(F31); newco.e[f3[1]][0] = newco.e[e4[0]][0] - 2.0 * dx; newco.e[f3[1]][1] = newco.e[e4[0]][1] - 2.0 * dy; newco.e[f3[1]][2] = newco.e[e4[0]][2] - 2.0 * dz; newco.e[f3[1]][3] = newco.e[e4[0]][3] - 2.0 * dw; } } ??? dx = (newco.e[e4[1]][0] - newco.e[e5[1]][0])/((double)order-2); ??? dy = (newco.e[e4[1]][1] - newco.e[e5[1]][1])/((double)order-2); ??? dz = (newco.e[e4[1]][2] - newco.e[e5[1]][2])/((double)order-2); ??? dw = (newco.e[e4[1]][3] - newco.e[e5[1]][3])/((double)order-2); { if ((PresentNode(F32))) { if (! net){ assert(! F32->exists); } f3[2] = NewNumVer(F32); newco.e[f3[2]][0] = newco.e[e4[1]][0] - 1.0 * dx; newco.e[f3[2]][1] = newco.e[e4[1]][1] - 1.0 * dy; newco.e[f3[2]][2] = newco.e[e4[1]][2] - 1.0 * dz; newco.e[f3[2]][3] = newco.e[e4[1]][3] - 1.0 * dw; } } } } else if (order == 5){ Node_t F00 = OrgV(ncor[i].right[ 3]); ??? F01 = OrgV(ncor[i].right[ 8]); ??? F02 = OrgV(ncor[i].right[ 6]); ??? F03 = OrgV(ncor[i].right[15]); ??? F04 = OrgV(ncor[i].right[13]); ??? F05 = OrgV(ncor[i].right[11]); ??? F10 = OrgV(ncor[i].left [ 3]); ??? F11 = OrgV(ncor[i].left [ 8]); ??? F12 = OrgV(ncor[i].left [ 6]); ??? F13 = OrgV(ncor[i].left [15]); ??? F14 = OrgV(ncor[i].left [13]); ??? F15 = OrgV(ncor[i].left [11]); ??? F30 = OrgV(ncor[i].back [ 3]); ??? F31 = OrgV(ncor[i].back [ 8]); ??? F32 = OrgV(ncor[i].back [ 6]); ??? F33 = OrgV(ncor[i].back [15]); ??? F34 = OrgV(ncor[i].back [13]); ??? F35 = OrgV(ncor[i].back [11]); ??? F20 = OrgV(ncor[i].front[ 3]); ??? F21 = OrgV(ncor[i].front[ 8]); ??? F22 = OrgV(ncor[i].front[ 6]); ??? F23 = OrgV(ncor[i].front[15]); ??? F24 = OrgV(ncor[i].front[13]); ??? F25 = OrgV(ncor[i].front[11]); { /* Right */ ??? dx = (newco.e[e1[0]][0] - newco.e[e2[0]][0])/((double)order-1); ??? dy = (newco.e[e1[0]][1] - newco.e[e2[0]][1])/((double)order-1); ??? dz = (newco.e[e1[0]][2] - newco.e[e2[0]][2])/((double)order-1); ??? dw = (newco.e[e1[0]][3] - newco.e[e2[0]][3])/((double)order-1); { if ((PresentNode(F00))) { if (! net){ assert(! F00->exists); } f0[0] = NewNumVer(F00); newco.e[f0[0]][0] = newco.e[e1[0]][0] - 1.0 * dx; newco.e[f0[0]][1] = newco.e[e1[0]][1] - 1.0 * dy; newco.e[f0[0]][2] = newco.e[e1[0]][2] - 1.0 * dz; newco.e[f0[0]][3] = newco.e[e1[0]][3] - 1.0 * dw; } if ((PresentNode(F02))) { if (! net){ assert(! F02->exists); } f0[2] = NewNumVer(F02); newco.e[f0[2]][0] = newco.e[e1[0]][0] - 2.0 * dx; newco.e[f0[2]][1] = newco.e[e1[0]][1] - 2.0 * dy; newco.e[f0[2]][2] = newco.e[e1[0]][2] - 2.0 * dz; newco.e[f0[2]][3] = newco.e[e1[0]][3] - 2.0 * dw; } if ((PresentNode(F05))) { if (! net){ assert(! F05->exists); } f0[5] = NewNumVer(F05); newco.e[f0[5]][0] = newco.e[e1[0]][0] - 3.0 * dx; newco.e[f0[5]][1] = newco.e[e1[0]][1] - 3.0 * dy; newco.e[f0[5]][2] = newco.e[e1[0]][2] - 3.0 * dz; newco.e[f0[5]][3] = newco.e[e1[0]][3] - 3.0 * dw; } } ??? dx = (newco.e[e1[1]][0] - newco.e[e2[1]][0])/((double)order-2); ??? dy = (newco.e[e1[1]][1] - newco.e[e2[1]][1])/((double)order-2); ??? dz = (newco.e[e1[1]][2] - newco.e[e2[1]][2])/((double)order-2); ??? dw = (newco.e[e1[1]][3] - newco.e[e2[1]][3])/((double)order-2); { if ((PresentNode(F01))) { if (! net){ assert(! F01->exists); } f0[1] = NewNumVer(F01); newco.e[f0[1]][0] = newco.e[e1[1]][0] - 1.0 * dx; newco.e[f0[1]][1] = newco.e[e1[1]][1] - 1.0 * dy; newco.e[f0[1]][2] = newco.e[e1[1]][2] - 1.0 * dz; newco.e[f0[1]][3] = newco.e[e1[1]][3] - 1.0 * dw; } if ((PresentNode(F04))) { if (! net){ assert(! F04->exists); } f0[4] = NewNumVer(F04); newco.e[f0[4]][0] = newco.e[e1[1]][0] - 2.0 * dx; newco.e[f0[4]][1] = newco.e[e1[1]][1] - 2.0 * dy; newco.e[f0[4]][2] = newco.e[e1[1]][2] - 2.0 * dz; newco.e[f0[4]][3] = newco.e[e1[1]][3] - 2.0 * dw; } } ??? dx = (newco.e[e1[2]][0] - newco.e[e2[2]][0])/((double)order-3); ??? dy = (newco.e[e1[2]][1] - newco.e[e2[2]][1])/((double)order-3); ??? dz = (newco.e[e1[2]][2] - newco.e[e2[2]][2])/((double)order-3); ??? dw = (newco.e[e1[2]][3] - newco.e[e2[2]][3])/((double)order-3); { if ((PresentNode(F03))) { if (! net){ assert(! F03->exists); } f0[3] = NewNumVer(F03); newco.e[f0[3]][0] = newco.e[e1[2]][0] - 1.0 * dx; newco.e[f0[3]][1] = newco.e[e1[2]][1] - 1.0 * dy; newco.e[f0[3]][2] = newco.e[e1[2]][2] - 1.0 * dz; newco.e[f0[3]][3] = newco.e[e1[2]][3] - 1.0 * dw; } } /* Left */ ??? dx = (newco.e[e0[0]][0] - newco.e[e4[3]][0])/((double)order-1); ??? dy = (newco.e[e0[0]][1] - newco.e[e4[3]][1])/((double)order-1); ??? dz = (newco.e[e0[0]][2] - newco.e[e4[3]][2])/((double)order-1); ??? dw = (newco.e[e0[0]][3] - newco.e[e4[3]][3])/((double)order-1); { if ((PresentNode(F10))) { if (! net){ assert(! F10->exists); } f1[0] = NewNumVer(F10); newco.e[f1[0]][0] = newco.e[e0[0]][0] - 1.0 * dx; newco.e[f1[0]][1] = newco.e[e0[0]][1] - 1.0 * dy; newco.e[f1[0]][2] = newco.e[e0[0]][2] - 1.0 * dz; newco.e[f1[0]][3] = newco.e[e0[0]][3] - 1.0 * dw; } if ((PresentNode(F11))) { if (! net){ assert(! F11->exists); } f1[1] = NewNumVer(F11); newco.e[f1[1]][0] = newco.e[e0[0]][0] - 2.0 * dx; newco.e[f1[1]][1] = newco.e[e0[0]][1] - 2.0 * dy; newco.e[f1[1]][2] = newco.e[e0[0]][2] - 2.0 * dz; newco.e[f1[1]][3] = newco.e[e0[0]][3] - 2.0 * dw; } if ((PresentNode(F13))) { if (! net){ assert(! F13->exists); } f1[3] = NewNumVer(F13); newco.e[f1[3]][0] = newco.e[e0[0]][0] - 3.0 * dx; newco.e[f1[3]][1] = newco.e[e0[0]][1] - 3.0 * dy; newco.e[f1[3]][2] = newco.e[e0[0]][2] - 3.0 * dz; newco.e[f1[3]][3] = newco.e[e0[0]][3] - 3.0 * dw; } } ??? dx = (newco.e[e0[1]][0] - newco.e[e4[2]][0])/((double)order-2); ??? dy = (newco.e[e0[1]][1] - newco.e[e4[2]][1])/((double)order-2); ??? dz = (newco.e[e0[1]][2] - newco.e[e4[2]][2])/((double)order-2); ??? dw = (newco.e[e0[1]][3] - newco.e[e4[2]][3])/((double)order-2); { if ((PresentNode(F12))) { if (! net){ assert(! F12->exists); } f1[2] = NewNumVer(F12); newco.e[f1[2]][0] = newco.e[e0[1]][0] - 1.0 * dx; newco.e[f1[2]][1] = newco.e[e0[1]][1] - 1.0 * dy; newco.e[f1[2]][2] = newco.e[e0[1]][2] - 1.0 * dz; newco.e[f1[2]][3] = newco.e[e0[1]][3] - 1.0 * dw; } if ((PresentNode(F14))) { if (! net){ assert(! F14->exists); } f1[4] = NewNumVer(F14); newco.e[f1[4]][0] = newco.e[e0[1]][0] - 2.0 * dx; newco.e[f1[4]][1] = newco.e[e0[1]][1] - 2.0 * dy; newco.e[f1[4]][2] = newco.e[e0[1]][2] - 2.0 * dz; newco.e[f1[4]][3] = newco.e[e0[1]][3] - 2.0 * dw; } } ??? dx = (newco.e[e0[2]][0] - newco.e[e4[1]][0])/((double)order-3); ??? dy = (newco.e[e0[2]][1] - newco.e[e4[1]][1])/((double)order-3); ??? dz = (newco.e[e0[2]][2] - newco.e[e4[1]][2])/((double)order-3); ??? dw = (newco.e[e0[2]][3] - newco.e[e4[1]][3])/((double)order-3); { if ((PresentNode(F15))) { if (! net){ assert(! F15->exists); } f1[5] = NewNumVer(F15); newco.e[f1[5]][0] = newco.e[e0[2]][0] - 1.0 * dx; newco.e[f1[5]][1] = newco.e[e0[2]][1] - 1.0 * dy; newco.e[f1[5]][2] = newco.e[e0[2]][2] - 1.0 * dz; newco.e[f1[5]][3] = newco.e[e0[2]][3] - 1.0 * dw; } } /* Front */ ??? dx = (newco.e[e3[0]][0] - newco.e[e5[0]][0])/((double)order-1); ??? dy = (newco.e[e3[0]][1] - newco.e[e5[0]][1])/((double)order-1); ??? dz = (newco.e[e3[0]][2] - newco.e[e5[0]][2])/((double)order-1); ??? dw = (newco.e[e3[0]][3] - newco.e[e5[0]][3])/((double)order-1); { if ((PresentNode(F20))) { if (! net){ assert(! F20->exists); } f2[0] = NewNumVer(F20); newco.e[f2[0]][0] = newco.e[e3[0]][0] - 1.0 * dx; newco.e[f2[0]][1] = newco.e[e3[0]][1] - 1.0 * dy; newco.e[f2[0]][2] = newco.e[e3[0]][2] - 1.0 * dz; newco.e[f2[0]][3] = newco.e[e3[0]][3] - 1.0 * dw; } if ((PresentNode(F21))) { if (! net){ assert(! F21->exists); } f2[1] = NewNumVer(F21); newco.e[f2[1]][0] = newco.e[e3[0]][0] - 2.0 * dx; newco.e[f2[1]][1] = newco.e[e3[0]][1] - 2.0 * dy; newco.e[f2[1]][2] = newco.e[e3[0]][2] - 2.0 * dz; newco.e[f2[1]][3] = newco.e[e3[0]][3] - 2.0 * dw; } if ((PresentNode(F23))) { if (! net){ assert(! F23->exists); } f2[3] = NewNumVer(F23); newco.e[f2[3]][0] = newco.e[e3[0]][0] - 3.0 * dx; newco.e[f2[3]][1] = newco.e[e3[0]][1] - 3.0 * dy; newco.e[f2[3]][2] = newco.e[e3[0]][2] - 3.0 * dz; newco.e[f2[3]][3] = newco.e[e3[0]][3] - 3.0 * dw; } } ??? dx = (newco.e[e3[1]][0] - newco.e[e5[1]][0])/((double)order-2); ??? dy = (newco.e[e3[1]][1] - newco.e[e5[1]][1])/((double)order-2); ??? dz = (newco.e[e3[1]][2] - newco.e[e5[1]][2])/((double)order-2); ??? dw = (newco.e[e3[1]][3] - newco.e[e5[1]][3])/((double)order-2); { if ((PresentNode(F22))) { if (! net){ assert(! F22->exists); } f2[2] = NewNumVer(F22); newco.e[f2[2]][0] = newco.e[e3[1]][0] - 1.0 * dx; newco.e[f2[2]][1] = newco.e[e3[1]][1] - 1.0 * dy; newco.e[f2[2]][2] = newco.e[e3[1]][2] - 1.0 * dz; newco.e[f2[2]][3] = newco.e[e3[1]][3] - 1.0 * dw; } if ((PresentNode(F24))) { if (! net){ assert(! F24->exists); } f2[4] = NewNumVer(F24); newco.e[f2[4]][0] = newco.e[e3[1]][0] - 2.0 * dx; newco.e[f2[4]][1] = newco.e[e3[1]][1] - 2.0 * dy; newco.e[f2[4]][2] = newco.e[e3[1]][2] - 2.0 * dz; newco.e[f2[4]][3] = newco.e[e3[1]][3] - 2.0 * dw; } } ??? dx = (newco.e[e3[2]][0] - newco.e[e5[2]][0])/((double)order-3); ??? dy = (newco.e[e3[2]][1] - newco.e[e5[2]][1])/((double)order-3); ??? dz = (newco.e[e3[2]][2] - newco.e[e5[2]][2])/((double)order-3); ??? dw = (newco.e[e3[2]][3] - newco.e[e5[2]][3])/((double)order-3); { if ((PresentNode(F25))) { if (! net){ assert(! F25->exists); } f2[5] = NewNumVer(F25); newco.e[f2[5]][0] = newco.e[e3[2]][0] - 1.0 * dx; newco.e[f2[5]][1] = newco.e[e3[2]][1] - 1.0 * dy; newco.e[f2[5]][2] = newco.e[e3[2]][2] - 1.0 * dz; newco.e[f2[5]][3] = newco.e[e3[2]][3] - 1.0 * dw; } } /* Back */ ??? dx = (newco.e[e4[0]][0] - newco.e[e5[0]][0])/((double)order-1); ??? dy = (newco.e[e4[0]][1] - newco.e[e5[0]][1])/((double)order-1); ??? dz = (newco.e[e4[0]][2] - newco.e[e5[0]][2])/((double)order-1); ??? dw = (newco.e[e4[0]][3] - newco.e[e5[0]][3])/((double)order-1); { if ((PresentNode(F30))) { if (! net){ assert(! F30->exists); } f3[0] = NewNumVer(F30); newco.e[f3[0]][0] = newco.e[e4[0]][0] - 1.0 * dx; newco.e[f3[0]][1] = newco.e[e4[0]][1] - 1.0 * dy; newco.e[f3[0]][2] = newco.e[e4[0]][2] - 1.0 * dz; newco.e[f3[0]][3] = newco.e[e4[0]][3] - 1.0 * dw; } if ((PresentNode(F31))) { if (! net){ assert(! F31->exists); } f3[1] = NewNumVer(F31); newco.e[f3[1]][0] = newco.e[e4[0]][0] - 2.0 * dx; newco.e[f3[1]][1] = newco.e[e4[0]][1] - 2.0 * dy; newco.e[f3[1]][2] = newco.e[e4[0]][2] - 2.0 * dz; newco.e[f3[1]][3] = newco.e[e4[0]][3] - 2.0 * dw; } if ((PresentNode(F33))) { if (! net){ assert(! F33->exists); } f3[3] = NewNumVer(F33); newco.e[f3[3]][0] = newco.e[e4[0]][0] - 3.0 * dx; newco.e[f3[3]][1] = newco.e[e4[0]][1] - 3.0 * dy; newco.e[f3[3]][2] = newco.e[e4[0]][2] - 3.0 * dz; newco.e[f3[3]][3] = newco.e[e4[0]][3] - 3.0 * dw; } } ??? dx = (newco.e[e4[1]][0] - newco.e[e5[1]][0])/((double)order-2); ??? dy = (newco.e[e4[1]][1] - newco.e[e5[1]][1])/((double)order-2); ??? dz = (newco.e[e4[1]][2] - newco.e[e5[1]][2])/((double)order-2); ??? dw = (newco.e[e4[1]][3] - newco.e[e5[1]][3])/((double)order-2); { if ((PresentNode(F32))) { if (! net){ assert(! F32->exists); } f3[2] = NewNumVer(F32); newco.e[f3[2]][0] = newco.e[e4[1]][0] - 1.0 * dx; newco.e[f3[2]][1] = newco.e[e4[1]][1] - 1.0 * dy; newco.e[f3[2]][2] = newco.e[e4[1]][2] - 1.0 * dz; newco.e[f3[2]][3] = newco.e[e4[1]][3] - 1.0 * dw; } if ((PresentNode(F34))) { if (! net){ assert(! F34->exists); } f3[4] = NewNumVer(F34); newco.e[f3[4]][0] = newco.e[e4[1]][0] - 2.0 * dx; newco.e[f3[4]][1] = newco.e[e4[1]][1] - 2.0 * dy; newco.e[f3[4]][2] = newco.e[e4[1]][2] - 2.0 * dz; newco.e[f3[4]][3] = newco.e[e4[1]][3] - 2.0 * dw; } } ??? dx = (newco.e[e4[2]][0] - newco.e[e5[2]][0])/((double)order-3); ??? dy = (newco.e[e4[2]][1] - newco.e[e5[2]][1])/((double)order-3); ??? dz = (newco.e[e4[2]][2] - newco.e[e5[2]][2])/((double)order-3); ??? dw = (newco.e[e4[2]][3] - newco.e[e5[2]][3])/((double)order-3); { if ((PresentNode(F35))) { if (! net){ assert(! F35->exists); } f3[5] = NewNumVer(F35); newco.e[f3[5]][0] = newco.e[e4[2]][0] - 1.0 * dx; newco.e[f3[5]][1] = newco.e[e4[2]][1] - 1.0 * dy; newco.e[f3[5]][2] = newco.e[e4[2]][2] - 1.0 * dz; newco.e[f3[5]][3] = newco.e[e4[2]][3] - 1.0 * dw; } } } } /* nodes on the octahedron barycenter. */ if (order == 2) { if ((PresentNode(mocta[i][0]))) { if (! net){ assert(! mocta[i][0]->exists); } ??? n = NewNumVer(mocta[i][0]); ??? b0 = Add(newco.e[e3[0]],newco.e[e1[0]]); ??? b1 = Add(newco.e[e4[0]],newco.e[e2[0]]); ??? b = Add(b0,b1); { newco.e[n] = Scale(1.0/((double)4), b); } } } else if (order == 3){ if ((PresentNode(mocta[i][0]))) { if (! net){ assert(! mocta[i][0]->exists); } ??? n = NewNumVer(mocta[i][0]); ??? b0 = Add(Add(newco.e[f2[0]]; with (newco.e[e3[0]]),newco.e[f1[0]]), ??? b1 = Add(Add(newco.e[e1[0]],newco.e[e0[0]]),newco.e[f0[0]]); ??? b = Add(b0,b1); { newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][1]))) { if (! net){ assert(! mocta[i][1]->exists); } ??? n = NewNumVer(mocta[i][1]); ??? b0 = Add(Add(newco.e[f2[0]],newco.e[f3[0]]),newco.e[e5[1]]); ??? b1 = Add(Add(newco.e[f1[0]],newco.e[e4[1]]),newco.e[e3[1]]); ??? b = Add(b0,b1); { MyAssert(newco.e[f2[0]]); MyAssert(newco.e[f3[0]]); MyAssert(newco.e[e5[1]]); MyAssert(newco.e[f1[0]]); MyAssert(newco.e[e4[1]]); MyAssert(newco.e[e3[1]]); newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][2]))) { if (! net){ assert(! mocta[i][2]->exists); } ??? n = NewNumVer(mocta[i][2]); ??? b0 = Add(Add(newco.e[f2[0]]; with (newco.e[f3[0]]),newco.e[e5[0]]), double b1 = Add(Add(newco.e[e1[1]],newco.e[f0[0]]),newco.e[e2[1]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][3]))) { if (! net){ assert(! mocta[i][3]->exists); } ??? n = NewNumVer(mocta[i][3]); ??? b0 = Add(Add(newco.e[f3[0]]; with (newco.e[f1[0]]),newco.e[e4[0]]), double b1 = Add(Add(newco.e[f0[0]],newco.e[e0[1]]),newco.e[e2[0]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } } else if (order == 4){ if ((PresentNode(mocta[i][0]))) { if (! net){ assert(! mocta[i][0]->exists); } ??? n = NewNumVer(mocta[i][0]); ??? b0 = Add(Add(newco.e[e1[0]]; with (newco.e[e0[0]]),newco.e[f0[0]]), double b1 = Add(Add(newco.e[f1[0]],newco.e[e3[0]]),newco.e[f2[0]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][3]))) { if (! net){ assert(! mocta[i][3]->exists); } ??? n = NewNumVer(mocta[i][3]); ??? b0 = Add(Add(newco.e[e3[2]]; with (newco.e[f2[2]]),newco.e[e5[2]]), double b1 = Add(Add(newco.e[f1[1]],newco.e[e4[2]]),newco.e[f3[2]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][5]))) { if (! net){ assert(! mocta[i][5]->exists); } ??? n = NewNumVer(mocta[i][5]); ??? b0 = Add(Add(newco.e[f2[1]]; with (newco.e[e1[2]]),newco.e[e5[0]]), double b1 = Add(Add(newco.e[f3[1]],newco.e[e2[2]]),newco.e[f0[1]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][6]))) { if (! net){ assert(! mocta[i][6]->exists); } ??? n = NewNumVer(mocta[i][6]); ??? b0 = Add(Add(newco.e[f0[2]]; with (newco.e[e0[2]]),newco.e[e2[0]]), double b1 = Add(Add(newco.e[f1[2]],newco.e[e4[0]]),newco.e[f3[0]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } ??? dx = (newco.e[f1[1]][0] - newco.e[f0[1]][0])/((double)order-2); ??? dy = (newco.e[f1[1]][1] - newco.e[f0[1]][1])/((double)order-2); ??? dz = (newco.e[f1[1]][2] - newco.e[f0[1]][2])/((double)order-2); ??? dw = (newco.e[f1[1]][3] - newco.e[f0[1]][3])/((double)order-2); ??? p0 = newco.e[f1[1]][0] - 1.0 * dx; ??? p1 = newco.e[f1[1]][1] - 1.0 * dy; ??? p2 = newco.e[f1[1]][2] - 1.0 * dz; ??? p3 = newco.e[f1[1]][3] - 1.0 * dw; with ( p == (r4_t){p0,p1,p2,p3} ){ if ((PresentNode(inter[i][0]))) { assert( NOT inter[i][0]->exists); ??? n = NewNumVer(inter[i][0]); { newco.e[n] = p; } } if ((PresentNode(mocta[i][1]))) { if (! net){ assert(! mocta[i][1]->exists); } ??? n = NewNumVer(mocta[i][1]); ??? b0 = Add(Add(newco.e[e3[1]]; with (newco.e[f2[0]]),newco.e[f2[2]]), double b1 = Add(Add(newco.e[f1[0]],newco.e[f1[1]]),p); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][2]))) { if (! net){ assert(! mocta[i][2]->exists); } ??? n = NewNumVer(mocta[i][2]); ??? b0 = Add(Add(newco.e[f2[0]]; with (newco.e[e1[1]]),newco.e[f2[1]]), double b1 = Add(Add(newco.e[f0[0]],newco.e[f0[1]]),p); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][4]))) { if (! net){ assert(! mocta[i][4]->exists); } ??? n = NewNumVer(mocta[i][4]); ??? b0 = Add(Add(newco.e[f2[2]]; with (newco.e[f2[1]]),newco.e[e5[1]]), double b1 = Add(Add(newco.e[f3[2]],newco.e[f3[1]]),p); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][7]))) { if (! net){ assert(! mocta[i][7]->exists); } ??? n = NewNumVer(mocta[i][7]); ??? b0 = Add(Add(newco.e[f0[0]]; with (newco.e[e0[1]]),newco.e[f0[2]]), double b1 = Add(Add(newco.e[f1[0]],newco.e[f1[2]]),p); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][8]))) { if (! net){ assert(! mocta[i][8]->exists); } ??? n = NewNumVer(mocta[i][8]); ??? b0 = Add(Add(newco.e[f0[1]]; with (newco.e[f0[2]]),newco.e[e2[1]]), double b1 = Add(Add(newco.e[f3[0]],newco.e[f3[1]]),p); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][9]))) { if (! net){ assert(! mocta[i][9]->exists); } ??? n = NewNumVer(mocta[i][9]); ??? b0 = Add(Add(newco.e[f1[2]]; with (newco.e[f1[1]]),newco.e[e4[1]]), double b1 = Add(Add(newco.e[f3[0]],newco.e[f3[2]]),p); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } } } else if (order == 5){ if ((PresentNode(mocta[i][0]))) { if (! net){ assert(! mocta[i][0]->exists); } ??? n = NewNumVer(mocta[i][0]); ??? b0 = Add(Add(newco.e[e1[0]]; with (newco.e[e0[0]]),newco.e[f0[0]]), double b1 = Add(Add(newco.e[f1[0]],newco.e[e3[0]]),newco.e[f2[0]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][6]))) { if (! net){ assert(! mocta[i][6]->exists); } ??? n = NewNumVer(mocta[i][6]); ??? b0 = Add(Add(newco.e[f1[3]]; with (newco.e[e3[3]]),newco.e[e4[3]]), double b1 = Add(Add(newco.e[f3[5]],newco.e[e5[3]]),newco.e[f2[5]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][9]))) { if (! net){ assert(! mocta[i][9]->exists); } ??? n = NewNumVer(mocta[i][9]); ??? b0 = Add(Add(newco.e[e1[3]]; with (newco.e[f0[3]]),newco.e[e2[3]]), double b1 = Add(Add(newco.e[f2[3]],newco.e[e5[0]]),newco.e[f3[3]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][10]))) { if (! net){ assert(! mocta[i][10]->exists); } ??? n = NewNumVer(mocta[i][10]); ??? b0 = Add(Add(newco.e[f0[5]]; with (newco.e[e0[3]]),newco.e[e2[0]]), double b1 = Add(Add(newco.e[f1[5]],newco.e[e4[0]]),newco.e[f3[0]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } ??? dx = (newco.e[f1[2]][0] - newco.e[f2[1]][0])/((double)order-3); ??? dy = (newco.e[f1[2]][1] - newco.e[f2[1]][1])/((double)order-3); ??? dz = (newco.e[f1[2]][2] - newco.e[f2[1]][2])/((double)order-3); ??? dw = (newco.e[f1[2]][3] - newco.e[f2[1]][3])/((double)order-3); ??? Q0 = newco.e[f1[2]][0] - 1.0 * dx; ??? Q1 = newco.e[f1[2]][1] - 1.0 * dy; ??? Q2 = newco.e[f1[2]][2] - 1.0 * dz; ??? Q3 = newco.e[f1[2]][3] - 1.0 * dw; with ( double q1 = (r4_t){Q0,Q1,Q2,Q3} ){ if ((PresentNode(mocta[i][1]))) { if (! net){ assert(! mocta[i][1]->exists); } ??? n = NewNumVer(mocta[i][1]); ??? b0 = Add(Add(newco.e[e3[1]]; with (newco.e[f2[0]]),newco.e[f2[2]]), double b1 = Add(Add(newco.e[f1[0]],newco.e[f1[1]]),q1); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][2]))) { if (! net){ assert(! mocta[i][2]->exists); } ??? n = NewNumVer(mocta[i][2]); ??? b0 = Add(Add(newco.e[e1[1]]; with (newco.e[f0[0]]),newco.e[f0[1]]), double b1 = Add(Add(newco.e[f2[0]],newco.e[f2[1]]),q1); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][13]))) { if (! net){ assert(! mocta[i][13]->exists); } ??? n = NewNumVer(mocta[i][13]); ??? b0 = Add(Add(newco.e[f0[0]]; with (newco.e[e0[1]]),newco.e[f0[2]]), double b1 = Add(Add(newco.e[f1[0]],newco.e[f1[2]]),q1); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } /* first internal node: q1 */ if ((PresentNode(inter[i][0]))) { assert( NOT inter[i][0]->exists); ??? n = NewNumVer(inter[i][0]); { newco.e[n] = q1; } } ??? dx = (newco.e[f1[5]][0] - newco.e[f2[3]][0])/((double)order-2); ??? dy = (newco.e[f1[5]][1] - newco.e[f2[3]][1])/((double)order-2); ??? dz = (newco.e[f1[5]][2] - newco.e[f2[3]][2])/((double)order-2); ??? dw = (newco.e[f1[5]][3] - newco.e[f2[3]][3])/((double)order-2); ??? p0 = newco.e[f1[5]][0] - 1.0 * dx; ??? p1 = newco.e[f1[5]][1] - 1.0 * dy; ??? p2 = newco.e[f1[5]][2] - 1.0 * dz; ??? p3 = newco.e[f1[5]][3] - 1.0 * dw; with ( double q2 = (r4_t){p0,p1,p2,p3}; double r0 = newco.e[f1[5]][0] - 2.0 * dx; double r1 = newco.e[f1[5]][1] - 2.0 * dy; double r2 = newco.e[f1[5]][2] - 2.0 * dz; double r3 = newco.e[f1[5]][3] - 2.0 * dw; double q3 = (r4_t){r0,r1,r2,r3}; double dx = (newco.e[f1[4]][0] - newco.e[f2[4]][0])/((double)order-3); double dy = (newco.e[f1[4]][1] - newco.e[f2[4]][1])/((double)order-3); double dz = (newco.e[f1[4]][2] - newco.e[f2[4]][2])/((double)order-3); double dw = (newco.e[f1[4]][3] - newco.e[f2[4]][3])/((double)order-3); double t0 = newco.e[f1[4]][0] - 1.0 * dx; double t1 = newco.e[f1[4]][1] - 1.0 * dy; double t2 = newco.e[f1[4]][2] - 1.0 * dz; double t3 = newco.e[f1[4]][3] - 1.0 * dw; double q4 = (r4_t){t0,t1,t2,t3} ){ /* internal nodes: q2, q3, q4 */ if ((PresentNode(inter[i][1]))) { assert(! inter[i][1]->exists); ??? n = NewNumVer(inter[i][1]); { newco.e[n] = q4; } } if ((PresentNode(inter[i][2]))) { assert(! inter[i][2]->exists); ??? n = NewNumVer(inter[i][2]); { newco.e[n] = q3; } } if ((PresentNode(inter[i][3]))) { assert(! inter[i][3]->exists); ??? n = NewNumVer(inter[i][3]); { newco.e[n] = q2; } } if ((PresentNode(mocta[i][7]))) { if (! net){ assert(! mocta[i][7]->exists); } ??? n = NewNumVer(mocta[i][7]); ??? b0 = Add(Add(newco.e[f2[5]]; with (newco.e[f2[4]]),newco.e[e5[2]]), double b1 = Add(Add(newco.e[f3[5]],newco.e[f3[4]]),q4); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][8]))) { if (! net){ assert(! mocta[i][8]->exists); } ??? n = NewNumVer(mocta[i][8]); ??? b0 = Add(Add(newco.e[f2[4]]; with (newco.e[f2[3]]),newco.e[e5[1]]), double b1 = Add(Add(newco.e[f3[4]],newco.e[f3[3]]),q3); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][3]))) { if (! net){ assert(! mocta[i][3]->exists); } ??? n = NewNumVer(mocta[i][3]); ??? b0 = Add(Add(newco.e[e3[2]]; with (newco.e[f2[2]]),newco.e[f2[5]]), double b1 = Add(Add(newco.e[f1[1]],newco.e[f1[3]]),q4); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][4]))) { if (! net){ assert(! mocta[i][4]->exists); } ??? n = NewNumVer(mocta[i][4]); ??? b0 = Add(Add(newco.e[f2[2]]; with (newco.e[f2[1]]),newco.e[f2[4]]), double b1 = Add(Add(q1,q3),q4); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][5]))) { if (! net){ assert(! mocta[i][5]->exists); } ??? n = NewNumVer(mocta[i][5]); ??? b0 = Add(Add(newco.e[f2[1]]; with (newco.e[e1[2]]),newco.e[f2[3]]), double b1 = Add(Add(newco.e[f0[1]],newco.e[f0[3]]),q3); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][12]))) { if (! net){ assert(! mocta[i][12]->exists); } ??? n = NewNumVer(mocta[i][12]); ??? b0 = Add(Add(newco.e[f3[0]]; with (newco.e[f3[1]]),newco.e[e2[1]]), double b1 = Add(Add(newco.e[f0[4]],newco.e[f0[5]]),q2); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][16]))) { if (! net){ assert(! mocta[i][16]->exists); } ??? n = NewNumVer(mocta[i][16]); ??? b0 = Add(Add(newco.e[e4[1]]; with (newco.e[f3[0]]),newco.e[f3[2]]), double b1 = Add(Add(newco.e[f1[5]],newco.e[f1[4]]),q2); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][18]))) { if (! net){ assert(! mocta[i][18]->exists); } ??? n = NewNumVer(mocta[i][18]); ??? b0 = Add(Add(newco.e[e4[2]]; with (newco.e[f3[2]]),newco.e[f3[5]]), double b1 = Add(Add(newco.e[f1[4]],newco.e[f1[3]]),q4); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][19]))) { if (! net){ assert(! mocta[i][19]->exists); } ??? n = NewNumVer(mocta[i][19]); ??? b0 = Add(Add(newco.e[f3[2]]; with (newco.e[f3[1]]),newco.e[f3[4]]), double b1 = Add(Add(q2,q3),q4); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][15]))) { if (! net){ assert(! mocta[i][15]->exists); } ??? n = NewNumVer(mocta[i][15]); ??? b0 = Add(Add(newco.e[f3[1]]; with (newco.e[e2[2]]),newco.e[f3[3]]), double b1 = Add(Add(newco.e[f0[3]],newco.e[f0[4]]),q3); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][11]))) { if (! net){ assert(! mocta[i][11]->exists); } ??? n = NewNumVer(mocta[i][11]); ??? b0 = Add(Add(newco.e[f0[2]]; with (newco.e[f0[5]]),q2), double b1 = Add(Add(newco.e[e0[2]],newco.e[f1[2]]), newco.e[f1[5]]); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][14]))) { if (! net){ assert(! mocta[i][14]->exists); } ??? n = NewNumVer(mocta[i][14]); ??? b0 = Add(Add(newco.e[f0[1]]; with (newco.e[f0[2]]),newco.e[f0[4]]), double b1 = Add(Add(q1,q2),q3); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } if ((PresentNode(mocta[i][17]))) { if (! net){ assert(! mocta[i][17]->exists); } ??? n = NewNumVer(mocta[i][17]); ??? b0 = Add(Add(newco.e[f1[2]]; with (newco.e[f1[1]]),newco.e[f1[4]]), double b1 = Add(Add(q1,q2), q4); b == Add(b0,b1) ){ newco.e[n] = Scale(1.0/((double)6), b); } } } } } } return newco; } /* END SettingCoords */ PROCEDURE GlueTetrahedra(Place_t @p, Place_t b) /* This procedure realizes the gluing of two single tetrahedra. */ { if ((Pneg(Spin(a)) == NULL) && (Pneg(b)!=NULL)){ EVAL Triangulation.Glue(Spin(a),b, 1, TRUE); } else if ((Pneg(a) == NULL) && (Pneg(b) == NULL)){ EVAL Triangulation.Glue(a,Spin(b), 1, TRUE); } else { fprintf(stderr,"BuildRefinement: Not gluing some triangular walls\n"); Process.Exit¦(1); } } /* END GlueTetrahedra */ PROCEDURE GlueMacroTetrahedra(ar,br: REF Place_vec_t) /* This procedure realizes the gluing of two macro-tetrahedra trough the triangulated macro-walls. */ { for (i = 0 TO ((ar^).ne)-1){ GlueTetrahedra(ar[i],br[i]); } } /* END GlueMacroTetrahedra */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 1, 5); o->detail = argparser_keyword_present(pp, "-detail"); o->fixed = argparser_keyword_present(pp, "-fixed"); o->net = argparser_keyword_present(pp, "-net"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: BuildRefinement \\\n" \ " -inFileTp \\\n" \ " -inFileSt \\\n"); fprintf(stderr, " -outFile \\\n" \ " -order [ -detail ] \\\n" \ " [ -fixed ] [ -net ]\n"); END¦ } } return o; } /* END GetOptions */ PROCEDURE ModSetGrade( uint ord; rco: Refine.Corner; bool_t Right,Left,Front,Back; ) /* Set @{edge->?}s and spheres underling on the boundary of a tetrahedron as thin cylinders and small spheres. */ void ResetNodeonNet(Place_t @p) { Node_t vn = OrgV(a); { vn->exists = FALSE; } } ResetNodeonNet; PROCEDURE Reset@{Edge->?}OnNet(Place_t @p) == { Edge_t en = PEdge(a); { en->exists = FALSE; } } Reset@{Edge->?}OnNet; void SetGrade1() { /* nothing */ } SetGrade1; void SetGrade2() { /* 3 @{edge->?}s and 0 nodes for each wall of the refined tetrahedron. */ /* On the right side. */ if (! Right) { Reset@{Edge->?}OnNet(PrevE(rco.right[0])); Reset@{Edge->?}OnNet( rco.right[3]); Reset@{Edge->?}OnNet(NextE (rco.right[2])); } /* On the left side. */ if (! Left) { Reset@{Edge->?}OnNet(PrevE(rco.left[0])); Reset@{Edge->?}OnNet( rco.left[2]); Reset@{Edge->?}OnNet(NextE (rco.left[1])); } /* On the front side. */ if (! Front) { Reset@{Edge->?}OnNet( rco.front[0]); Reset@{Edge->?}OnNet(NextE (rco.front[1])); Reset@{Edge->?}OnNet(NextE (rco.front[2])); } /* On the back side. */ if (! Back) { Reset@{Edge->?}OnNet( rco.back [0]); Reset@{Edge->?}OnNet(NextE (rco.back [1])); Reset@{Edge->?}OnNet(PrevE(rco.back [2])); } } SetGrade2; void SetGrade3() { /* 9 @{edge->?}s and 1 nodes for each wall of the refined tetrahedron. */ SetGrade2(); /* On the right side. */ if (! Right) { Reset@{Edge->?}OnNet(PrevE(rco.right[3])); Reset@{Edge->?}OnNet(PrevE(rco.right[1])); Reset@{Edge->?}OnNet( rco.right[8]); Reset@{Edge->?}OnNet(NextE (rco.right[7])); Reset@{Edge->?}OnNet( rco.right[6]); Reset@{Edge->?}OnNet(NextE (rco.right[5])); ResetNodeonNet(rco.right[3]); } /* On the left side. */ if (! Left) { Reset@{Edge->?}OnNet(PrevE(rco.left[1])); Reset@{Edge->?}OnNet(PrevE(rco.left[3])); Reset@{Edge->?}OnNet(NextE (rco.left[4])); Reset@{Edge->?}OnNet( rco.left[5]); Reset@{Edge->?}OnNet(NextE (rco.left[6])); Reset@{Edge->?}OnNet( rco.left[7]); ResetNodeonNet(rco.left[3]); } /* On the front side. */ if (! Front) { Reset@{Edge->?}OnNet( rco.front[1]); Reset@{Edge->?}OnNet( rco.front[3]); Reset@{Edge->?}OnNet(NextE (rco.front[4])); Reset@{Edge->?}OnNet(NextE (rco.front[5])); Reset@{Edge->?}OnNet(NextE (rco.front[6])); Reset@{Edge->?}OnNet(NextE (rco.front[7])); ResetNodeonNet(rco.front[3]); } /* On the back side. */ if (! Back) { Reset@{Edge->?}OnNet( rco.back [1]); Reset@{Edge->?}OnNet( rco.back [3]); Reset@{Edge->?}OnNet(NextE (rco.back [4])); Reset@{Edge->?}OnNet(PrevE(rco.back [5])); Reset@{Edge->?}OnNet(NextE (rco.back [6])); Reset@{Edge->?}OnNet(PrevE(rco.back [7])); ResetNodeonNet(rco.back[3]); } } SetGrade3; void SetGrade4() { /* 18 @{edge->?}s and 3 nodes for each wall of the refined tetrahedron. */ SetGrade3(); /* On the right side. */ if (! Right) { Reset@{Edge->?}OnNet(PrevE(rco.right[8])); Reset@{Edge->?}OnNet(PrevE(rco.right[6])); Reset@{Edge->?}OnNet(PrevE(rco.right[4])); Reset@{Edge->?}OnNet( rco.right[15]); Reset@{Edge->?}OnNet(NextE (rco.right[14])); Reset@{Edge->?}OnNet( rco.right[13]); Reset@{Edge->?}OnNet(NextE (rco.right[12])); Reset@{Edge->?}OnNet( rco.right[11]); Reset@{Edge->?}OnNet(NextE (rco.right[10])); ResetNodeonNet(rco.right[8]); ResetNodeonNet(rco.right[6]); } /* On the left side. */ if (! Left) { Reset@{Edge->?}OnNet(PrevE(rco.left[4])); Reset@{Edge->?}OnNet(PrevE(rco.left[6])); Reset@{Edge->?}OnNet(PrevE(rco.left[8])); Reset@{Edge->?}OnNet(NextE (rco.left[9 ])); Reset@{Edge->?}OnNet( rco.left[10]); Reset@{Edge->?}OnNet(NextE (rco.left[11])); Reset@{Edge->?}OnNet( rco.left[12]); Reset@{Edge->?}OnNet(NextE (rco.left[13])); Reset@{Edge->?}OnNet( rco.left[14]); ResetNodeonNet(rco.left[8]); ResetNodeonNet(rco.left[6]); } /* On the front side. */ if (! Front) { Reset@{Edge->?}OnNet( rco.front[4]); Reset@{Edge->?}OnNet( rco.front[6]); Reset@{Edge->?}OnNet( rco.front[8]); Reset@{Edge->?}OnNet(NextE (rco.front[ 9])); Reset@{Edge->?}OnNet(NextE (rco.front[10])); Reset@{Edge->?}OnNet(NextE (rco.front[11])); Reset@{Edge->?}OnNet(NextE (rco.front[12])); Reset@{Edge->?}OnNet(NextE (rco.front[13])); Reset@{Edge->?}OnNet(NextE (rco.front[14])); ResetNodeonNet(rco.front[8]); ResetNodeonNet(rco.front[6]); } /* On the back side. */ if (! Back) { Reset@{Edge->?}OnNet( rco.back [4]); Reset@{Edge->?}OnNet( rco.back [6]); Reset@{Edge->?}OnNet( rco.back [8]); Reset@{Edge->?}OnNet(NextE (rco.back [ 9])); Reset@{Edge->?}OnNet(PrevE(rco.back [10])); Reset@{Edge->?}OnNet(NextE (rco.back [11])); Reset@{Edge->?}OnNet(PrevE(rco.back [12])); Reset@{Edge->?}OnNet(NextE (rco.back [13])); Reset@{Edge->?}OnNet(PrevE(rco.back [14])); ResetNodeonNet(rco.back[8]); ResetNodeonNet(rco.back[6]); } } SetGrade4; void SetGrade5() { /* 10 @{edge->?}s and 6 nodes for each wall of the refined tetrahedron. */ SetGrade4(); /* On the right side. */ if (! Right) { Reset@{Edge->?}OnNet(PrevE(rco.right[15])); Reset@{Edge->?}OnNet(PrevE(rco.right[13])); Reset@{Edge->?}OnNet(PrevE(rco.right[11])); Reset@{Edge->?}OnNet(PrevE(rco.right[ 9])); Reset@{Edge->?}OnNet( rco.right[24]); Reset@{Edge->?}OnNet(NextE (rco.right[23])); Reset@{Edge->?}OnNet( rco.right[22]); Reset@{Edge->?}OnNet(NextE (rco.right[21])); Reset@{Edge->?}OnNet( rco.right[20]); Reset@{Edge->?}OnNet(NextE (rco.right[19])); Reset@{Edge->?}OnNet( rco.right[18]); Reset@{Edge->?}OnNet(NextE (rco.right[17])); ResetNodeonNet(rco.right[15]); ResetNodeonNet(rco.right[13]); ResetNodeonNet(rco.right[11]); } /* On the left side. */ if (! Left) { Reset@{Edge->?}OnNet(PrevE(rco.left[ 9])); Reset@{Edge->?}OnNet(PrevE(rco.left[11])); Reset@{Edge->?}OnNet(PrevE(rco.left[13])); Reset@{Edge->?}OnNet(PrevE(rco.left[15])); Reset@{Edge->?}OnNet(NextE (rco.left[16])); Reset@{Edge->?}OnNet( rco.left[17]); Reset@{Edge->?}OnNet(NextE (rco.left[18])); Reset@{Edge->?}OnNet( rco.left[19]); Reset@{Edge->?}OnNet(NextE (rco.left[20])); Reset@{Edge->?}OnNet( rco.left[21]); Reset@{Edge->?}OnNet(NextE (rco.left[22])); Reset@{Edge->?}OnNet( rco.left[23]); ResetNodeonNet(rco.left[15]); ResetNodeonNet(rco.left[13]); ResetNodeonNet(rco.left[11]); } /* On the front side. */ if (! Front) { Reset@{Edge->?}OnNet( rco.front[ 9]); Reset@{Edge->?}OnNet( rco.front[11]); Reset@{Edge->?}OnNet( rco.front[13]); Reset@{Edge->?}OnNet( rco.front[15]); Reset@{Edge->?}OnNet(NextE (rco.front[16])); Reset@{Edge->?}OnNet(NextE (rco.front[17])); Reset@{Edge->?}OnNet(NextE (rco.front[18])); Reset@{Edge->?}OnNet(NextE (rco.front[19])); Reset@{Edge->?}OnNet(NextE (rco.front[20])); Reset@{Edge->?}OnNet(NextE (rco.front[21])); Reset@{Edge->?}OnNet(NextE (rco.front[22])); Reset@{Edge->?}OnNet(NextE (rco.front[23])); ResetNodeonNet(rco.front[15]); ResetNodeonNet(rco.front[13]); ResetNodeonNet(rco.front[11]); } /* On the back side. */ if (! Back) { Reset@{Edge->?}OnNet( rco.back [ 9]); Reset@{Edge->?}OnNet( rco.back [11]); Reset@{Edge->?}OnNet( rco.back [13]); Reset@{Edge->?}OnNet( rco.back [15]); Reset@{Edge->?}OnNet(NextE (rco.back [16])); Reset@{Edge->?}OnNet(PrevE(rco.back [17])); Reset@{Edge->?}OnNet(NextE (rco.back [18])); Reset@{Edge->?}OnNet(PrevE(rco.back [19])); Reset@{Edge->?}OnNet(NextE (rco.back [20])); Reset@{Edge->?}OnNet(PrevE(rco.back [21])); Reset@{Edge->?}OnNet(NextE (rco.back [22])); Reset@{Edge->?}OnNet(PrevE(rco.back [23])); ResetNodeonNet(rco.back[15]); ResetNodeonNet(rco.back[13]); ResetNodeonNet(rco.back[11]); } } SetGrade5; { if ( ord == 1){ SetGrade1(); } else if (ord == 2){ SetGrade2(); } else if (ord == 3){ SetGrade3(); } else if (ord == 4){ SetGrade4(); } else if (ord == 5){ SetGrade5(); } else { fprintf(stderr,"Order must be less equal to 5\n"); assert(ord <= 5); } } /* END ModSetGrade */ { DoIt() } BuildRefinement. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/CameraPath.c #define PROG_NAME "CameraPath" #define PROG_DESC "???" #define PROG_VERS "1.0" #define CameraPath_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Generates equally spaced sample points along a closed path around the origin Writes the sample points as camera positions in the format expected by the "Wire4"-Interactive 4D Wireframe Display Program (".w4"). Also writes a plain text file with one point per line (preceded by its integer ID). Implemented by stolfi 16-10-2000 */ #include // #INCLUDE #include #include //#include TYPE double Row3I = ARRAY [0..2] OF INTEGER; double double = double; typedef struct Options_t { char *outFile; /* Output file name prefix */ double dist; /* Nominal distance from origin */ bool_t normalize; /* If TRUE, normalize From-To vectors to length "dist". */ uint renderPoints; /* Subsampling ratio for camera positions.*/ wire4Points: uint; /* Number of nodes on path for Wire4 plotting. */ To4: r4_t; /* Look at point */ Up4: r4_t; /* Head-up point */ Over4: r4_t; /* Hyperhead-up point */ } <* FATAL Wr.Failure, Thread.Alerted, OSError.E); void WriteColor(FILE *wr, *c: Row3I) /* Write colors in RGB mode */ { Mis.WriteInt(wr,c[0]); fprintf(wr," "); Mis.WriteInt(wr,c[1]); fprintf(wr," "); Mis.WriteInt(wr,c[2]); } /* END WriteColor */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? cmt = "Made by CameraPath on " & Today() & "\n"; ??? w4 = FileWr.Open(o->outFile & ".w4"); ??? txt = FileWr.Open(o->outFile & ".from4"); { WriteComments(w4,o,cmt); WriteComments(txt,o,cmt); WriteWire4Header(w4, 3.0*o->dist); SamplePath(o,w4,txt); fclose(w4); fclose(txt); return 0; } void WriteComments ( FILE *wr, <*UNUSED);*o: Options_t; char *cmt; ) { filefmt_write_comment(wr,cmt,'#'); fprintf(wr, "\n"); } /* END WriteComments */ void WriteWire4Header(FILE *wr, dist: double) { fprintf(wr, "DegreeRing@{Edge->?}s"); fprintf(wr," 0"); fprintf(wr,"\nDepthCueLevels 10"); fprintf(wr,"\nFogDensity 0.5"); fprintf(wr,"\n"); fprintf(wr, "\nFrom4: " & Fmt.LongReal(dist) & " 00 00 00"); fprintf(wr, "\nTo4 : 00 00 00 00"); fprintf(wr, "\nUp4 : 00 00 +1 00"); fprintf(wr, "\nOver4: 00 00 00 +1"); fprintf(wr, "\nVangle4: 30"); fprintf(wr, "\n"); fprintf(wr, "\nFrom3: " & Fmt.LongReal(dist) & " 00 00"); fprintf(wr, "\nTo3 : 00 00 00"); fprintf(wr, "\nUp3 : 00 00 +1"); fprintf(wr, "\nVangle3: 30"); fprintf(wr, "\n"); } /* END WriteWire4Header */ PROCEDURE SamplePath(*o: Options_t; w4: Wr.T; txt: Wr.T) Row3I vcolor = Row3I{100,100,100}; ecolor : Row3I = Row3I{0,255,255}; vradius : REAL = 1.0; eradius : REAL = 1.0; CONST TwoPi == 6.28318530717958648; { r4_t EvalPath(t: double) { ??? r1 = 1.0; with ( t1 == t, c1 == cos(t1), s1 == sin(t1), double r2 = 0.7, t2 == 2.0*t + 1.0, c2 == cos(t2), s2 == sin(t2); double p = (r4_t){ r1*c1, r1*s1, r2*c2, r2*s2 } ){ if (o->normalize) { return r4_Scale(o->dist, r4_Dir(p)); } else { return r4_Scale(o->dist, p); } } } EvalPath; PROCEDURE ComputeSampleTimes(nSteps: uint): REF double_vec_t == /* Returns array "t[0..nSteps]" with "nSteps+1" equally spaced times in "[0..TwoPi]", including "t[0] == 0" and "t[nSteps] == TwoPi". */ r4_t pAnt; VAR { ??? fns = ((double)nSteps); ??? rt = double_vec_new(nSteps + 1); with (t == rt^ DO pAnt = EvalPath(0.0); t[0] = 0.0; for (i = 1; i <= (nSteps); i++) { ??? fi = FLOAT(i,double), ti == TwoPi*fi/fns; { t[i] = ti;} } return rt; } } ComputeSampleTimes; PROCEDURE ComputePathLengths( *t: double_vec_t; ): REF double_vec_t == /* Computes "s[i]" == path length from "t==0" to each "t[i]" */ double *sAnt; pAnt: r4_t; { ??? nt = (t.ne); ??? rs = double_vec_new(nt); with (s == rs^ DO pAnt = EvalPath(0.0); sAnt = 0.0; for (i = 0; i < nt; i++) { ??? pi = EvalPath(t[i]); { sAnt = sAnt + r4_Dist(pAnt, pi); s[i] = sAnt; pAnt = pi } } return rs; } } ComputePathLengths; r4_vec_t *ComputeEquallySpacedPoints( *t: double_vec_t;/*Times of some sample points along curve */ *s: double_vec_t;/*Lengths to those sample points along curve */ uint np; )== /* Divides the interval "t[0]..t[(t.ne-1)]" into np equal intervals and returns an array with the beginning of each interval. */ uint *iCur; tGoal: double; { ??? nt = (t.ne); ??? rp = r4_vec_new(np); with (p == rp^, double sIni = s[0], sFin == s[(s.ne-1)], ds == sFin - sIni ){ assert(nt == (s.ne)); iCur = 0; for (k = 0; k < np; k++) { ??? sGoal = sIni + ds * ((double)k)/((double)np); { while (iCur < nt - 1) && (s[iCur+1] < sGoal){ iCur++; } if (iCur >= nt-1) { tGoal = t[nt-1] } else { ??? ds = s[iCur+1] - s[iCur], dt == t[iCur+1] - t[iCur]; { tGoal = t[iCur] + dt * (sGoal - s[iCur])/ds } } p[k] = EvalPath(tGoal); } } return rp; } } ComputeEquallySpacedPoints; void WriteCoord(FILE *wr, x: double) { fprintf(wr, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 4), 7)); } WriteCoord; void WritePoint4DForWire4( *c: r4_t; vcolor: Row3I; REAL vradius; ) { WriteCoord(w4,c[0]); fprintf(w4, " "); WriteCoord(w4,c[1]); fprintf(w4, " "); WriteCoord(w4,c[2]); fprintf(w4, " "); WriteCoord(w4,c[3]); fprintf(w4, " : "); WriteColor(w4, vcolor); fprintf(w4, " : "); Mis.WriteRadius(w4, vradius); fprintf(w4, "\n"); } WritePoint4DForWire4; void WritePoint4DAsText(*c: r4_t; uint i) { fprintf(txt, " " & Fmt.Int(i) & " "); WriteCoord(txt,c[0]); fprintf(txt, " "); WriteCoord(txt,c[1]); fprintf(txt, " "); WriteCoord(txt,c[2]); fprintf(txt, " "); WriteCoord(txt,c[3]); fprintf(txt, "\n"); } WritePoint4DAsText; { ??? nr = o->renderPoints; ??? nw = o->wire4Points; ??? ns = 50*MAX(nr; with ( nw), double t = ComputeSampleTimes(ns)^; double s = ComputePathLengths(t)^ ){ /* Camera positions for rendering */ ??? pr = ComputeEquallySpacedPoints(t, s, nr)^; { for (k = 0 TO (pr.ne-1)) { WritePoint4DAsText(pr[k],k); } }; /* Camera positions for wire4 */ fprintf(w4, "\n\nNodeList : "); fprintf(w4, Fmt.Int(nw+5) & "\n"); ??? pw = ComputeEquallySpacedPoints(t, s, nw)^; { for (k = 0 TO (pw.ne-1)) { WritePoint4DForWire4(pw[k],vcolor,vradius); } } /* reference axis nodes */ fprintf(w4, " 0 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 1 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 1 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 1 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 0 1 : 255 255 255 : 0\n"); fprintf(w4, "\n"); fprintf(w4, "\n@{Edge->?}List " & Fmt.Int(nw+4) & ":\n"); for (i = 0; i < nw; i++) { fprintf(w4, Fmt.Pad(Fmt.Int(i), 4) & " " \ Fmt.Pad(Fmt.Int((i+1) % nw),4)); fprintf(w4, " : "); /* color */ WriteColor(w4, ecolor); fprintf(w4, " : "); Mis.WriteRadius(w4, eradius); fprintf(w4, "\n"); } /* reference axis @{edge->?}s */ fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+1)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+2)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+3)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+4)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, "\nWallList 0\n"); fclose(w4); } } } /* END SamplePath */ Options_t *GetOptions(int argc, char **argv) Options_t *o = (Options_t *)malloc(sizeof(Options_t)); { argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-dist"); o->dist = pp.getNextLongReal(1.0d-10,1.0d+10); o->normalize = argparser_keyword_present(pp, "-normalize"); if ((argparser_keyword_present(pp, "-renderPoints"))) { o->renderPoints = argparser_get_next_int(pp, 1,10000); } else { o->renderPoints = 10; } if ((argparser_keyword_present(pp, "-wire4Points"))) { o->wire4Points = argparser_get_next_int(pp, 1,10000); } else { o->wire4Points = 10; } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: CameraPath \\\n" \ " -outFile \\\n" \ " -dist [ -normalize ] \\\n" \ " [ -renderPoints ] \\\n" \ " [ -wire4Points ]\n"); END¦ } } return o; } /* END GetOptions */ /* end CameraPath */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Circle.c #define PROG_NAME "Circle" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Circle_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " #include #include #include #include VAR uint n; teta: double = 0.0; double y; <* FATAL Wr.Failure, Thread.Alerted, Rd.EndOfFile, FloatMode.Trap, Rd.Failure, Lex.Error); INTEGER ReadInt() { return Scan.Int(Rd.GetLine(stdin)); } ReadInt; { fprintf(stderr, "Input an integer in the next line\n"); n = ReadInt(); ??? count = 360 DIV n; { for (i = 0; i < n; i++) { teta = FLOAT(count,double) + teta; ??? nr = FLOAT((teta * FLOAT(Math.Pi, double))/180.0); with(double), double x = cos(nr); double x2 = FLOAT(x * x,double) ){ if ((nr > FLOAT(Math.Pi,double))) { y = sqrt(1.0-x2); } else { y = -sqrt(1.0-x2); } fprintf(stderr, Fmt.LongReal(x) & " " & Fmt.LongReal(y) & "\n"); } } } } circle. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Cross.c /* Programa para testar as propriedades do produto cruzado no R4. 1) Se os vetores nao sao l. i. retorna vetor nulo 2) Se mudar a ordem dos operandos muda o sentido do vetor "cross" 3) O vetor "cross" \'e ortogonal aos 3 vetores argumentos 4) O produto cross de A x b x c onde A == K a equivale a: K (a x b x c) */ // #INCLUDE #include #include #include { with ( double p1 = (r4_t){ 1.00000, 1.00000, 1.0000, 1.0000}; double p2 = (r4_t){ 2.00000, 0.30000, 3.0000, 3.0000}; double p3 = (r4_t){-0.14700, -0.79300, 0.66301, -0.000}; double pp = r4_Scale(2.0, p1); double m = r4_cross(p1,p2,p3); double n = r4_cross(pp,p2,p3); double nn = r4_Scale(2.0, m); double a = r4_dot(m,p1); double b = r4_dot(m,p2); double c = r4_dot(m,p3) ){ Mis.WritePoint(Stdio.stdout, n); fprintf(Stdio.stdout, "\n"); Mis.WritePoint(Stdio.stdout, nn); fprintf(Stdio.stdout, "\n"); fprintf(Stdio.stdout, Fmt.LongReal(a) & " " & Fmt.LongReal(b) \ " " & Fmt.LongReal(c) & "\n"); } } Cross. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/DegreeOfNode.c #define PROG_NAME "DegreeOfNode" #define PROG_DESC "???" #define PROG_VERS "1.0" #define DegreeOfNode_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This module prints the degree of each node. */ #include #include // #INCLUDE TYPE typedef struct Options_t { char *inFile; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { fprintf(stderr, "node label degree\n"); fprintf(stderr, "----------------------\n"); for (i = 0; i < top->node.ne; i++) { ??? a = top->node[i]; ??? v = Triangulation.OrgV(a); ??? l = v.label; ??? d = Triangulation.DegreeOfNode(a); { fprintf(stderr, Fmt.Pad(Fmt.Int(i),5) & " " & l \ Fmt.Pad(Fmt.Int(d),7) & "\n"); } } return 0; } Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr,"Usage: DegreeOfNode \\\n"); fprintf(stderr," -inFile \n"); END¦ } } return o; } /* END GetOptions */ /* end DegreeOfNode */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Depthcueing4D.c #define PROG_NAME "Depthcueing4D" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Depthcueing4D_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program performs the 4D depth-cueing by POVray tracer. The include file must be process with the "povray-3.1a-1" version in ~stolfi/pkg/povray-3.1a-1/PUB/sun4-SunOS-5.5 . Revisions: 09-05-2000: Added in the rendering the nodes (spheres) 20-05-2000: Added the silhouette walls. 19-07-2000: Added the original walls. */ #include #include // #INCLUDE #include // #INCLUDE #include #include #include // #INCLUDE #include // #INCLUDE // #INCLUDE r4_t bari ; cmap : REF ARRAY OF Row3I; Wa,Wb,Wc,Wd : r4_t; vstack = NEW(REF uint_vec_t , INIT_STACK_SIZE); /* stack for nodes */ vtop : uint = 0; /* top for the above stack */ CONST double Epsilon = 0.0000000001; double INIT_STACK_SIZE = 100000; /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ TYPE double Row3I = ARRAY[0..2] OF INTEGER; double FourNodes_t = RECORD u, v, w, x: uint; } typedef struct Options_t { char *inFileTp; char *inFileSt; char *outFile; char *projectionName; bool_t autoProject; double normalize; /* Normalize al nodes onto the S^3 with that radius. */ From4: r4_t; /* */ To4: r4_t; /* 4D viewing parameters as expected by the */ Up4: r4_t; /* "Wire4"- Interactive 4D Wireframe Display */ Over4: r4_t; /* Program. */ Vangle4: double; /* */ bool_t printDepth; bool_t colormap; dc_ColorFar: Row3I; dc_ColorNear: Row3I; double dc_DepthFar; double dc_DepthNear; INTEGER dc_Levels; bool_t silhouette; /* draws the silhouette walls */ color : frgb_t; /* attributes of color and opacity for silhouette */ REAL opacity; /* walls; Transparent (opacity==1) Opaque (opacity==0)*/ bool_t walls; /* draws the original walls */ } PROCEDURE WL(double x) : char *== { return(Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 2), 6)); } /* END WL */ bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { assert(d!=0.0); if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ char *newcmt; { ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? c = rc^; ??? rc3 = NEW(REF Tridimensional.Coord3D; with ( top->node.ne), double c3 = rc3^; double rdepth = double_vec_new(top->node.ne); double depth = rdepth^; double cmt = tc.cmt & "\nProjected in " & o->projectionName \ ": " & o->outFile & ".st3 on " & Today() ){ cmap = NEW(REF ARRAY OF Row3I, o->dc_Levels); SetColorMap(o); if (o->colormap){ PrintColorMap(o); } if (o->normalize > 0.0) { fprintf(stderr, "projecting nodes onto the unit S^3\n"); NormalizeNodeCoords(c, o->normalize); } if (o->autoProject ){ SelectProjection(o, c, top); newcmt = cmt & "\nWith AutoProject"; } else { newcmt = cmt & "\nParameters: " \ "\nFrom4: " & WL(o->From4[0]) & WL(o->From4[1]) & WL(o->From4[2]) & WL(o->From4[3]) \ "\nTo4: " & WL(o->To4[0]) & WL(o->To4[1]) & WL(o->To4[2]) & WL(o->To4[3]) \ "\nUp4: " & WL(o->Up4[0]) & WL(o->Up4[1]) & WL(o->Up4[2]) & WL(o->Up4[3]) \ "\nOver4: " & WL(o->Over4[0]) & WL(o->Over4[1]) & WL(o->Over4[2]) & WL(o->Over4[3]) \ "\nVangle4: " & WL(o->Vangle4); } ProjectTo3D(o, c, c3, depth, top); if (0 == strcmp(o->projectionName, "Parallel"))) { WritePOVFile(o, depth, o->outFile & "-Par", top, c3); } else if (0 == strcmp(o->projectionName, "Perspective"))){ WritePOVFile(o, depth, o->outFile & "-Per", top, c3); } bari = Triangulation.Barycenter(top, c); return 0; } void NormalizeNodeCoords(VAR c: Coords_t; newR: double) { ??? b = Barycenter(c); { for (i = 0 TO (c.ne-1)) { ??? p = c[i], q == r4_Sub(p, b), r == r4_Norm(q); { if (r > 0.0){ p = r4_Scale(newR/r, q);} } } } } NormalizeNodeCoords; r4_t Barycenter(*c: Coords_t) r4_t B = (r4_t){0.0, ..}; VAR { for (i = 0 TO (c.ne-1)){ B = r4_Add(B, c[i]); } return r4_Scale(1.0/FLOAT((c.ne), double), B); } Barycenter; void CalcV4Matrix(*o: Options_t) /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ VAR double norm; { /* Calculate Wd, the 4th coordinate basis vector and line-of-sight. */ Wd = r4_Sub(o->To4,o->From4); norm = r4_Norm(Wd); if (norm < Epsilon) { fprintf(stderr,"4D To Point and From Point are the same\n"); Process.Exit¦(1); } Wd = r4_Scale(1.0/norm, Wd); /* Calculate Wa, the X-axis basis vector. */ Wa = r4_cross(o->Up4,o->Over4,Wd); norm = r4_Norm(Wa); if (norm < Epsilon) { fprintf(stderr, "4D up,over and view vectors are not perpendicular\n"); Process.Exit¦(1); } Wa = r4_Scale(1.0/norm, Wa); /* Calculate Wb, the perpendicularized Up vector. */ Wb = r4_cross(o->Over4,Wd,Wa); norm = r4_Norm(Wb); if (norm < Epsilon) { fprintf(stderr,"Invalid 4D over vector\n"); Process.Exit¦(1); } Wb = r4_Scale(1.0/norm, Wb); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ Wc = r4_cross(Wd,Wa,Wb); } CalcV4Matrix; PROCEDURE ProjectTo3D( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Coords_t *c; VAR c3: Tridimensional.Coord3D; double_vec_t depth, ElemTableRec_t *top) VAR Tan2Vangle4, Data4Radius, pconst, rtemp: double; TempV : r4_t; { ??? angle = o->Vangle4/2.0; ??? angler = (FLOAT(Math.Pi, double)*angle)/180.0); with( ) { Tan2Vangle4 = Math.tan(angler); } /* Find the radius of the 4D data. The radius of the 4D data is the radius of the smallest enclosing sphere, centered at the To point. Note that during the loop through the nodes, Data4Radius holds the squared radius value. */ Data4Radius = 0.0; for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); ??? Temp4 = r4_Sub(c[v->num]; with (o->To4), double dist = r4_dot(Temp4,Temp4) ){ if (dist > Data4Radius) { Data4Radius = dist; } } } Data4Radius = sqrt(Data4Radius); fprintf(stderr,"Data4Radius: "& Fmt.Pad(Fmt.LongReal(Data4Radius, Fmt.Style.Fix, prec = 4),8)&"\n\n"); CalcV4Matrix(o); if (0 == strcmp(o->projectionName, "Parallel"))) { rtemp = 1.0 / Data4Radius; } else { pconst = 1.0 / Tan2Vangle4; } for (i = 0; i < top->node.ne; i++) { /* Transform the nodes from 4D World coordinates to 4D eye coordinates. */ Node_t v = OrgV(top->node.e[i]); { TempV = r4_Sub(c[v->num],o->From4); depth[v->num] = r4_dot(TempV,Wd); if (0 == strcmp(o->projectionName, "Perspective"))) { rtemp = pconst / depth[v->num]; }; if (o->printDepth) { fprintf(stderr, "v[" & Fmt.Pad(Fmt.Int(v->num),4) & "] depth == " \ Fmt.Pad(Fmt.LongReal(depth[v->num],Fmt.Style.Fix,prec=4),8) & "\n"); } c3[v->num][0] = rtemp * r4_dot(TempV, Wa); c3[v->num][1] = rtemp * r4_dot(TempV, Wb); c3[v->num][2] = rtemp * r4_dot(TempV, Wc); } } } /* END ProjectTo3D */ PROCEDURE TetrahedronNodes(f:TriangulationPlace_t): ARRAY [0..3] OF uint { Place_t g = Tors(f); Place_t h = Tors(Clock(PrevE(f))); Node_t p = OrgV(g)->num; Node_t q = OrgV(NextE(g))->num; Node_t r = OrgV(PrevE(g))->num; Node_t s = OrgV(PrevE(h))->num; { return ARRAY [0..3] OF uint {p, q, r, s}; } } /* END TetrahedronNodes */ PROCEDURE SelectProjection( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Coords_t *c, ElemTableRec_t *top) norm: r4_t = (r4_t){0.0, ..}; { for (i = 0; i < top->cell.ne; i++){ ??? f = Srot(top.cell[i]); ??? k = TetrahedronNodes(f); ??? p = c[k[0]]; ??? q = c[k[1]]; ??? r = c[k[2]]; ??? s = c[k[3]]; ??? pq = r4_Sub(q; with ( p), double pr = r4_Sub(r, p); double ps = r4_Sub(s, p); double v = r4_cross(pq, pr, ps); double n = r4_Dir(v) ){ norm = r4_Add(norm, n) } } ??? m = r4_Norm(norm); { if (m < 1.0d-20) { norm = (r4_t){1.0, 0.0, ..} } else { norm = r4_Scale(1.0/m, norm) } } ??? bar = Triangulation.Barycenter(top; with ( c) ){ o->To4 = bar; o->From4 = r4_Add(o->To4, norm); SelectTwoIndepDirs(norm, o->Up4, o->Over4); o->Vangle4 = 120.0; } } /* END SelectProjection */ PROCEDURE SelectTwoIndepDirs( *u: r4_t; VAR v, w: r4_t; ) /* Selects two vectors "v", "w", independent of each other and of the given vector "u". */ m: uint = 0; { /* Find the largest coordinate of "u": */ for (i = 1; i < 4; i++){ if ((fabs(u[i]) > fabs(u[m]))){ m = i; } } for (i = 0; i < 4; i++){ v[i] = 0.0; w[i] = 0.0; } v[(m+1) % 4] = 1.0; w[(m+2) % 4] = 1.0; } /* END SelectTwoIndepDirs */ void WritePOVFile( Options_t *op; *depth: double_vec_t; char *name; *ElemTableRec_t *top; *c3: Tridimensional.Coord3D; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(name & ".inc"); { fprintf(wr, "// Include File: <" & name & ".inc>\n"); WritePOV(op, depth, wr, top, c3); fclose(wr) } } /* END WritePOVFile */ void WritePOV( Options_t *op; *depth: double_vec_t; wr: Wr.T; *ElemTableRec_t *top; *c3: Coord3D; ) void WritePOVCylinder4DC( *o,d: r3_t; REAL radius; *cr: ARRAY [0..1] OF R3.T; ) /* Defines a finity length cylinder without parallel end caps with 4D depthcueing. This effect is obtained by the use of color map that modified the pigments colors through the length cylinder. */ { fprintf(wr," cylinder {\n"); fprintf(wr," "); WritePOVPoint(wr,o); fprintf(wr, ",\n"); fprintf(wr," "); WritePOVPoint(wr,d); fprintf(wr, ",\n"); fprintf(wr," " & Fmt.Real(radius) & "\n"); fprintf(wr," open\n"); fprintf(wr," pigment {\n"); fprintf(wr," gradient "); WritePOVPoint(wr,r3_sub(d,o)); fprintf(wr,"\n"); fprintf(wr," color_map{\n"); fprintf(wr," [0.0 color "); WritePOVColor(wr,cr[0]); fprintf(wr,"]\n"); fprintf(wr," [1.0 color "); WritePOVColor(wr,cr[1]); fprintf(wr,"]\n"); fprintf(wr," }\n"); fprintf(wr," translate "); WritePOVPoint(wr,o); fprintf(wr,"\n"); fprintf(wr," }\n"); fprintf(wr," }\n\n"); fflush(wr); } WritePOVCylinder4DC; double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x compute us its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; frgb_t cr[1+1]; { for (i = 0; i < top->NE; i++){ ??? e = top->edge[i]; { if (e->exists) { ??? a = e.pa; Node_t ov = OrgV(a); Node_t dv = OrgV(Clock(a)); ??? or = ov->num; ??? de = dv->num; ??? cm = LineDepthCue(op; with (ov,dv,depth) ){ for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) { cr[i][j] = FLOAT(cm[i][j],REAL)/255.0; } } WritePOVCylinder4DC(c3[or], c3[de], e.radius, cr); ??? ov = (Node_t)(ov); { double dv = (Node_t)(dv) ){ if ((! Present(vstack,vtop,or))) { WritePOVSphere(wr,c3[or], ov.radius, cr[0], 0.0, TRUE); Save(vstack,vtop,ov->num); } if ((! Present(vstack,vtop,de))) { WritePOVSphere(wr,c3[de], dv.radius, cr[1], 0.0, TRUE); Save(vstack,vtop,dv->num); } } } } } } if (op.silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; ??? c = op.color; ??? t = op.opacity; { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WritePOVTriangle(wr,c3[un], c3[vn], c3[wn],c,t, TRUE); } } } } if (op.walls) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; ??? t3 = f.transp; ??? tp = (t3[0] + t3[1] + t3[2]) / 3.0; ??? co = f.color; { if (f->exists) { WritePOVTriangle(wr,c3[un], c3[vn], c3[wn], co, tp, TRUE); } } } } fflush(wr); } /* END WritePOV */ PROCEDURE LineDepthCue( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Node P,Q; *depth: double_vec_t; ) : ARRAY[0..1] OF Row3I == /* This function computes the colors for 4D depthcueing. The main approach used is to subdivide the pigment into dc_Levels subsegments, that is realized by the "gradient " implemented by J. Stolfi in the "povray-3.1a-1" version, where is an arbitrary vector. */ Row3I cd[1+1]; { ??? depthP = depth[P->num]; ??? depthQ = depth[Q->num]; ??? dc_DFar_DNear = o->dc_DepthFar - o->dc_DepthNear; ??? dscale = FLOAT(o->dc_Levels, double) / dc_DFar_DNear); with( ) { if (depthP < o->dc_DepthNear ){ cd[0] = Row3I{cmap[0][0],cmap[0][1],cmap[0][2]}; } else if (depthP > o->dc_DepthFar){ cd[0] = Row3I{cmap[o->dc_Levels-1][0], cmap[o->dc_Levels-1][1], cmap[o->dc_Levels-1][2]}; } else { cd[0] = Row3I{cmap[FLOOR(dscale*(depthP-o->dc_DepthNear))][0], cmap[FLOOR(dscale*(depthP-o->dc_DepthNear))][1], cmap[FLOOR(dscale*(depthP-o->dc_DepthNear))][2]}; } if (depthQ < o->dc_DepthNear ){ cd[1] = Row3I{cmap[0][0],cmap[0][1],cmap[0][2]}; } else if (depthQ > o->dc_DepthFar){ cd[1] = Row3I{cmap[o->dc_Levels-1][0], cmap[o->dc_Levels-1][1], cmap[o->dc_Levels-1][2]}; } else { cd[1] = Row3I{cmap[FLOOR(dscale*(depthQ-o->dc_DepthNear))][0], cmap[FLOOR(dscale*(depthQ-o->dc_DepthNear))][1], cmap[FLOOR(dscale*(depthQ-o->dc_DepthNear))][2]}; } return cd; } } LineDepthCue; PROCEDURE SetColorMap(*o: Options_t) /* Set up the depthcue color map. */ INTEGER *range; { for (rgb = 0; rgb < 3; rgb++){ range = o->dc_ColorFar[rgb] - o->dc_ColorNear[rgb]; if (range < 0) { range = range - 1; } else { range = range + 1; } for (i = 0; i < o->dc_Levels; i++) { cmap[i][rgb]= o->dc_ColorNear[rgb]+ (i*range) DIV o->dc_Levels; } } } SetColorMap; PROCEDURE PrintColorMap(*o: Options_t) /* Print the depthcue color map. */ { for (i = 0; i < o->dc_Levels; i++){ fprintf(stderr," cmap["&Fmt.Pad(Fmt.Int(i),2)&"] is"); for (rgb = 0; rgb < 3; rgb++) { fprintf(stderr, Fmt.Pad(Fmt.Int(cmap[i][rgb]), 4)); } fprintf(stderr,"\n"); } } /* END PrintColorMap */ PROCEDURE Save( Stack: REF uint_vec_t; uint *top,element; ) /* Saves the "element" on the stack "Stack". */ { Stack.El[top] = element; top++; } /* END Save */ bool_t Present( *Stack: REF uint_vec_t; uint top,element; ) /* Return TRUE if "element" its on the stack, FALSE c.c. */ nstack1: uint = top; { while (nstack1 > 0){ nstack1 = nstack1 - 1; if (Stack.El[nstack1] == element){ return TRUE; } } return FALSE; } Present; Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } argparser_get_keyword(pp, "-projection"); o->projectionName = argparser_get_next(pp); if ((! 0 == strcmp(o->projectionName, "Parallel") OR Text.Equal(o->projectionName, "Perspective")) THEN argparser_error(pp, "Bad projection \"" & argparser_get_next(pp) & "\"\n") } if ((argparser_keyword_present(pp, "-normalize"))) { /* Desired radius of model in R^4 */ o->normalize = pp.getNextLongReal(1.0d-10,1.0d+10); } else { o->normalize = 0.0 /* No normalization */ } if ((argparser_keyword_present(pp, "-autoProject"))) { o->autoProject = TRUE } else { if ((argparser_keyword_present(pp, "-From4"))) { for (j = 0; j < 4; j++) { o->From4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From4 = (r4_t){0.0,0.0,0.0,-3.0}; } if ((argparser_keyword_present(pp, "-To4"))) { for (j = 0; j < 4; j++) { o->To4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To4 = (r4_t){0.0,0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up4"))) { for (j = 0; j < 4; j++) { o->Up4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up4 = (r4_t){0.0,1.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Over4"))) { for (j = 0; j < 4; j++) { o->Over4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Over4 = (r4_t){0.0,0.0,1.0,0.0}; } } if ((argparser_keyword_present(pp, "-Vangle4"))) { o->Vangle4 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle4 = 25.0; } o->printDepth = argparser_keyword_present(pp, "-printDepth"); o->colormap = argparser_keyword_present(pp, "-colormap"); if ((argparser_keyword_present(pp, "-ColorFar"))) { for (j = 0; j < 3; j++) { o->dc_ColorFar[j] = argparser_get_next_int(pp, 0,255); } } else { o->dc_ColorFar= Row3I{255, 255, 255}; }; if ((argparser_keyword_present(pp, "-ColorNear"))) { for (j = 0; j < 3; j++) { o->dc_ColorNear[j] = argparser_get_next_int(pp, 0,255); } } else { o->dc_ColorNear= Row3I{0, 0, 0}; }; if ((argparser_keyword_present(pp, "-DepthNear"))) { o->dc_DepthNear = pp.getNextLongReal(-1000.0, 1000.0); } else { o->dc_DepthNear= 2.0; }; if ((argparser_keyword_present(pp, "-DepthFar"))) { o->dc_DepthFar = pp.getNextLongReal(-1000.0, 1000.0); } else { o->dc_DepthFar = 6.0; }; if ((argparser_keyword_present(pp, "-DepthCueLevels"))) { o->dc_Levels = argparser_get_next_int(pp, 0, 10000); } else { o->dc_Levels = 6; }; if ((argparser_keyword_present(pp, "-silhouette"))) { o->silhouette = TRUE; if ((argparser_keyword_present(pp, "-color"))) { for (j = 0; j < 3; j++) { o->color[j] = pp.getNextReal(0.0,1.0); } } else { o->color = (frgb_t){1.0,1.0,0.75}; } if ((argparser_keyword_present(pp, "-opacity"))) { o->opacity = pp.getNextReal(0.0,1.0); } else { o->opacity = 0.85; } } if ((argparser_keyword_present(pp, "-walls"))) { o->walls = TRUE; } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage:\n" \ " Depthcueing4D -inFileTp \\\n" \ " -inFileSt [ -outFile ] \\\n" \ " -projection [ Perspective | Parallel ] \\\n" \ " [ [ -autoProject ] | \\\n" \ " [ -From4 ] \\\n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ] \\\n" \ " ] [ -Vangle4 ] \\\n" \ " [ -printDepth ] [ -normalize ] [ -colormap ] \\\n" \ " [ -ColorFar ] \\\n" \ " [ -ColorNear ] \\\n" \ " [ -DepthFar ] [ -DepthNear ] \\\n" \ " [ -DepthCueLevels ] \\\n" \ " [ -silhouette [ -color | -opacity ] ] \\\n" \ " [ -walls ]\n"); END¦ } } return o; } /* END GetOptions */ /* end Depthcueing4D */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/DirectionEyes.c #define PROG_NAME "DirectionEyes" #define PROG_DESC "???" #define PROG_VERS "1.0" #define DirectionEyes_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " #include #include #include #include #include CONST up == (frgb_t){0.0,1.0,0.0}; VAR obs3,int3: frgb_t; double x; REAL ReadLong() { return Scan.Real(Rd.GetLine(Stdio.stdin)); } /* END ReadLong */ { x = Math.pow(2.0,1.0/3.0); fprintf(stderr,"Input the look_at vector (one component by line)\n\n"); fprintf(stderr,"look_at\n"); for (i = 0; i < 3; i++) { obs3[i] = ReadLong(); } fprintf(stderr, "raiz cubica de 2 " & Fmt.LongReal(x) & "\n"); fprintf(stderr, "Input the location camera vector\n\n"); fprintf(stderr, "location\n"); for (i = 0; i < 3; i++) { int3[i] = ReadLong(); } ??? view = R3.Sub(int3; with (obs3), cross == R3Extras.Cross(view,up), norm == R3.Norm(cross), dirR == R3.Scale(1.0/norm,cross), dirL == R3.Scale(-1.0/norm,cross) ){ fprintf(stderr, "Direction left eye\n"); for (i = 0; i < 3; i++) { fprintf(stderr,Fmt.Real(dirL[i]) & " "); } fprintf(stderr,"\n"); fprintf(stderr, "Direction right eye\n"); for (i = 0; i < 3; i++) { fprintf(stderr,Fmt.Real(dirR[i]) & " "); } fprintf(stderr,"\n"); } } DirectionEyes. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/DualMap.c #define PROG_NAME "DualMap" #define PROG_DESC "???" #define PROG_VERS "1.0" #define DualMap_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program builds the dual topology of any 3D map. This is, the node information in the primal correspond to the cell information in the dual, @{edge->?}s to walls, walls to @{edge->?}s and cells to nodes. The geometric configuration of the dual is computed from the primal by geometric duality, assuming the figure is a convex polytope. The geometry will be garbage otherwise. The color and material information is remade from scratch. Therefore this program is useful mostly for original maps and not for their refinements. */ #include #include #include #include // #INCLUDE // #INCLUDE #include #include CONST double BoolChars = Mis.BoolChars; TYPE typedef struct Options_t { char *inFileTp; /* primal topology file */ char *inFileSt; /* primal geometric file */ char *outFile; /* dual topology and geometric file */ bool_t polyroot; /* includes the cell root information */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? c = rc^; ??? com = tc.cmt & "\nProcessed by DualMap\n"; ??? name = o->outFile; ??? cd = ComputeDualState(top; with (c) ){ WriteDualTopology(name, top, com); WriteDualMaterials(name, top, com, o->polyroot); WriteState(name, top->cell.ne, cd^, com); return 0; } void WriteDualMaterials(char *name, ElemTableRec_t *top, char *com; bool_t root; ) <* FATAL Thread.Alerted, Wr.Failure , OSError.E); CONST double Black = (frgb_t){0.0, 0.0, 0.0}; double White = (frgb_t){1.0, 1.0, 1.0}; double LightYellow = (frgb_t){1.0, 1.0, 0.8}; double Opaque = (frgb_t){0.0, 0.0, 0.0}; double HalfTransp = (frgb_t){0.5, 0.5, 0.5}; { ??? ma = FileWr.Open(name & ".ma"); ??? vWidth = digits(MAX(1, top->node.ne - 1)); with ( double eWidth = digits(MAX(1,top->NE - 1)); double fWidth = digits(MAX(1,top->wall.ne - 1)); double pWidth = digits(MAX(1,top->cell.ne - 1)) ){ WriteHeader(ma,"materials","99-08-25"); if (((com != NULL) && ((*com) != 0))) { filefmt_write_comments(ma, com & "\n", '|') } filefmt_write_comments(ma, "nodes " & Fmt.Pad(Fmt.Int(top->cell.ne),6), '|'); filefmt_write_comments(ma, "@{edge->?}s " & Fmt.Pad(Fmt.Int(top->wall.ne),6), '|'); filefmt_write_comments(ma, "walls " & Fmt.Pad(Fmt.Int(top->NE),6), '|'); filefmt_write_comments(ma, "cells " & Fmt.Pad(Fmt.Int(top->node.ne),6), '|'); for (i = 0; i < top->cell.ne; i++) { ??? vexists = TRUE; ??? vfixed = FALSE; ??? vradius = 0.02; ??? vlabel = "VV"; { /* materials */ fprintf(ma, Fmt.Pad(Fmt.Int(i), pWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[vexists])); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[vfixed])); fprintf(ma, " "); WriteColor(ma, Black); fprintf(ma, " "); WriteColor(ma, Opaque); fprintf(ma, " "); WriteRadius(ma, vradius); fprintf(ma, " "); WriteLabel(ma, vlabel); fprintf(ma, "\n"); }; } filefmt_write_comments(ma, "\n@{Edge->?} data:\n", '|'); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? eexists = TRUE; ??? edegenerate = FALSE; ??? eradius = 0.01; { /* materials */ fprintf(ma, Fmt.Pad(Fmt.Int(f->num), fWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[eexists])); fprintf(ma, " "); WriteColor(ma, Black); fprintf(ma, " "); WriteColor(ma, Opaque); fprintf(ma, " "); WriteRadius(ma, eradius); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[edegenerate])); fprintf(ma, " "); fprintf(ma, Fmt.Pad(Fmt.Int(f->num), fWidth)); fprintf(ma, "\n"); } } filefmt_write_comments(ma, "\nWall data:\n", '|'); for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; ??? fexists = TRUE; ??? fdegenerate = FALSE; { fprintf(ma, Fmt.Pad(Fmt.Int(e->num), eWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[fexists])); fprintf(ma, " "); WriteColor(ma, LightYellow); fprintf(ma, " "); WriteColor(ma, HalfTransp); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[fdegenerate])); fprintf(ma, " "); fprintf(ma, Fmt.Pad(Fmt.Int(e->num), eWidth)); fprintf(ma, "\n"); } } if (top->node.ne!=0) { filefmt_write_comments(ma, "\nCell data:\n", '|'); } for (i = 0; i < top->node.ne; i++) { ??? pexists = TRUE; ??? pdegenerate = FALSE; { fprintf(ma, Fmt.Pad(Fmt.Int(i), vWidth)); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[pexists])); fprintf(ma, " "); WriteColor(ma, White); fprintf(ma, " "); WriteColor(ma, White); fprintf(ma, " "); fprintf(ma, Fmt.Char(BoolChars[pdegenerate])); if (root) { fprintf(ma, " "); fprintf(ma, Fmt.Pad(Fmt.Int(i), vWidth)); } fprintf(ma, "\n"); } } filefmt_write_footer(ma, "materials"); fclose(ma); } } /* END WriteDualMaterials */ Coords_t *ComputeDualState(ElemTableRec_t *top, * c: Coords_t )== VAR uint nv; a : r4_t; { ??? cd = NEW(REF Coords_t; with ( top->cell.ne) ){ for (i = 0; i < top->cell.ne; i++) { ??? da = Srot(top.cell[i]); ??? ptop = Triangulation.MakeCellTopology(da); { a = (r4_t){0.0, 0.0, 0.0, 0.0}; nv = 0; for (i = 0 TO LAST(ptop.vRef^)) { Node_t v = OrgV(ptop.vRef[i]); { if (v != NULL){ nv++; a = r4_Add(a, c[v->num]); } } } cd[i] = r4_Scale(1.0/FLOAT(ptop.node.ne,double), a); } } return cd; } } /* END ComputeDualState */ void WriteIntensity(FILE *wr, float r) { fprintf(wr, Fmt.Real(r, Fmt.Style.Fix, prec = 2)); } /* END WriteIntensity */ void WriteColor(FILE *wr, *c: frgb_t) { WriteIntensity(wr,c[0]); fprintf(wr, " "); WriteIntensity(wr,c[1]); fprintf(wr, " "); WriteIntensity(wr,c[2]); } /* END WriteColor */ void WriteRadius(FILE *wr, float r) { if (r == 0.00){ fprintf(wr, "0.00"); } else { fprintf(wr,Fmt.Real(r, prec = 2)); } } /* END WriteRadius */ void WriteLabel(FILE *wr, char *label) { fprintf(wr, label); } /* END WriteLabel */ void WriteState(char *name, uint *nv; Coords_t *c; com: char *= " "; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? st = FileWr.Open(name & ".st"); ??? vWidth = digits(nv- 1); { void WriteCoord(double x) { fprintf(st, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Sci, prec = 3), 7)); } WriteCoord; void WritePoint(*c: r4_t) { WriteCoord(c[0]); fprintf(st, " "); WriteCoord(c[1]); fprintf(st, " "); WriteCoord(c[2]); fprintf(st, " "); WriteCoord(c[3]); } WritePoint; { WriteHeader(st,"state","99-08-25"); fprintf(st, "nodes "); fprintf(st, Fmt.Int(nv) & "\n"); if (((com != NULL) && ((*com) != 0))) { filefmt_write_comments(st, com & "\n", '|') } filefmt_write_comments(st, "\nNode data:\n", '|'); for (i = 0; i < nv; i++) { /* state */ fprintf(st, Fmt.Pad(Fmt.Int(i), vWidth)); fprintf(st, " "); WritePoint(c[i]); fprintf(st, "\n"); } } filefmt_write_footer(st, "state"); fclose(st); } } /* END WriteState */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->polyroot = argparser_keyword_present(pp, "-polyroot"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: DualMap -inFileTp \\\n" \ " -inFileSt -outFile \\\n" \ " [-polyroot]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt(); } DualMap. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Explode.c #define PROG_NAME "Explode" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Explode_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program receives as input a single cell (the envelope) and produces a include file with the barycentric subdivision of walls (2-skeleton) and cells (3-skeleton) but in an exploding way. */ #define Explode_C_author \ "Modified by L.A.P.Lozada on 2000-05-19." #include #include #include #include // #INCLUDE // #INCLUDE #include // #INCLUDE TYPE typedef struct Options_t { char *inFileTp; /* Input file name (minus ".tp" extension) */ char *inFileSt; /* Input file name (minus ".st" extension) */ char *outFile; /* Output file name prefix */ char *projectionName; bool_t autoProject; From4: r4_t; /* */ To4: r4_t; /* 4D viewing parameters as expected by the */ Up4: r4_t; /* "Wire4"- Interactive 4D Wireframe Display */ Over4: r4_t; /* Program. */ Vangle4: double; /* */ bool_t explode; /* For explode the configuration */ Element element; /* Choose the element to explode (wall or cell) */ char *eleName; } double Element = {Wall, Cell}; CONST double Epsilon = 0.0000000001; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); uint NNE = 0; NNV: uint = 0; gi : REF ARRAY OF Place_vec_t; ElemTableRec_t ntop; vf : REF Node_vec_t; o : Options_t = GetOptions(); inc : FileWr.T; { ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? c = rc^; ??? half = Place_vec_new(2*top->wall.nelE)^; ??? vnew = Node_vec_new(top->node.ne)^; { if (o->explode) { if (o->element == Element.Wall) { inc = FileWr.Open(o->outFile & "-Ex-Wall.inc"); } else if ( o->element == Element.Cell){ inc = FileWr.Open(o->outFile & "-Ex-Cell.inc"); } } fprintf(stderr, "Subdividing from: " & o->inFileTp & ".tp\n"); gi = NEW(REF ARRAY OF Place_vec_t, top->cell.ne, 4); Node_vec_t vf = Node_vec_new(top->wall.ne); Place_t Half(Place_t @p) { ??? na = PWedge(a)->num; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? h = half[2*na + oa]; { if (sa == 0){ return h }else{ return Spin(h); } } } Half; bool_t CreateNode(Place_t @p) Place_t t = a; VAR { ??? fe = NARROW(PWedge(a)-> TriangulationWedge_t); { if (! fe.mark) { fe.mark = TRUE; do { ??? fe = NARROW(PWedge(t), TriangulationWedge_t); { fe.mark = TRUE; } t = NextF(t) } while (t != a); return TRUE; } return FALSE; } } CreateNode; void SetAllVhnum(Place_t @p, Node_t v) void SetVhnum(Place_t @p) { ??? fe = NARROW(PWedge(a)-> TriangulationWedge_t); { fe.vh = v; } } SetVhnum; Place_t t = a; VAR { do { SetVhnum(t); t = NextF(t); } while (t != a); } SetAllVhnum; Node Vhnum(Place_t @p) { ??? fe = NARROW(PWedge(a)-> TriangulationWedge_t); { return fe.vh; } } Vhnum; { /* Copy original nodes, save correspondence in "vnew" array: */ for (iu = 0; iu < top->node.ne; iu++) { ??? u = top->node[iu]; Node_t v = MakeNode(); { v->num = u->num; v->exists = u->exists; v.fixed = u.fixed; v.color = u.color; v.radius = u.radius; vnew[iu] = v } } /* Create two new wedges for each original wedge "fe". The new wedge corresponding to the origin half of "fe", with same spin and orientation, will be | Half(a) == Spin^s(half[2*PWedge(a)->num + s]) where s == SpinBit(a), s == OrientationBit(a) */ REF Node_vec_t ve = Node_vec_new(top->NE); uint i = 0; { for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? ho = half[2*ie + oa]; ??? hd = half[2*ie + 1 - oa]; ??? fe = NARROW(PWedge(a)-> with ( TriangulationWedge_t), double b = CreateNode(a) ){ if (b) { ve[i] = MakeNode(); ve[i]->num = top->node.ne + NNV; INC (NNV); ve[i]->exists = top->edge[fe.edge->num]->exists; ve[i].fixed = FALSE; ve[i].radius = fe.edge.radius; ve[i].color = fe.edge.color; SetAllVhnum(a, ve[i]); i++; } ho = MakeWedge(); ??? hoe = NARROW(PWedge(ho)-> TriangulationWedge_t); { hoe->num = NNE; NNE++; hoe.edge->exists = fe.edge->exists; hoe.edge.radius = fe.edge.radius; hoe.edge.color = fe.edge.color; } if (sa == 1){ ho = Spin(ho); } hd = MakeWedge(); ??? hde = NARROW(PWedge(hd)-> TriangulationWedge_t); { hde->num = NNE; NNE++; hde.edge->exists = fe.edge->exists; hde.edge.radius = fe.edge.radius; hde.edge.color = fe.edge.color; } if (sa == 1){ ho = Spin(ho); } SpliceEdges(ho, Clock(hd)); ??? m = Vhnum(a); { SetOrg(Clock(ho),ve[m->num-top->node.ne]); SetOrg(Clock(hd),ve[m->num-top->node.ne]); } SetOrg(ho, vnew[OrgV(a)->num]); SetOrg(hd, vnew[OrgV(Clock(a))->num]); } } } /* Connect the half-wedges as in the original triangulation */ for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((c!=a) && (NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } Place_t a = Clock(top->wedge[ie]); Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } } for (i = 0; i < top->wall.ne; i++) { vf[i] = MakeNode(); vf[i]->num = top->node.ne + NNV; INC (NNV); } for (i = 0; i < top->wall.ne; i++) { Place_t *a,b,c,d,aa; { ??? p = top->wall[i].pa; { aa = p; for (j = 0 TO Octf.DegreeOfEdge(p)-1) { ??? ha = Half(aa); ??? hac = Half(Clock(aa)); { a = MakeWedge(); PWedge(a)->num = NNE; NNE++; b = MakeWedge(); PWedge(b)->num = NNE; NNE++; c = MakeWedge(); PWedge(c)->num = NNE; NNE++; d = MakeWedge(); PWedge(d)->num = NNE; NNE++; SetOrg(a, OrgV(Clock(ha))); SetOrg(Clock(a),vf[i]); SetOrg(b,vf[i]); SetOrg(Clock(b), OrgV(ha)); SetNextE(ha,a); SetNextE(a,b); SetNextE(b,ha); SetRingWallInfo(a,PWall(a)); SetOrg(c, OrgV(Clock(hac))); SetOrg(Clock(c),vf[i]); SetOrg(d,vf[i]); SetOrg(Clock(d), OrgV(hac)); SetNextE(hac,c); SetNextE(c,d); SetNextE(d,hac); SetRingWallInfo(c,PWall(c)); SetNextF(a,c); SetNextF(c,a); SetOrgAll(a, OrgV(a)); } aa = NextE(aa); } } } } for (i = 0; i < top->wall.ne; i++) { Place_t *aa; { ??? p = top->wall[i].pa; { aa = p; for (j = 0 TO Octf.DegreeOfEdge(p)-1) { ??? hpc = Half(Clock(aa)); ??? hq = Half(NextE(aa)); { SetNextF(PrevE(hq), PrevE(hpc)); SetRingEdgeInfo(PrevE(hq),PEdge(PrevE(hq))); } aa = NextE(aa); } SetOrgAll(PrevE(Half(p)),vf[i]); } } } for (i = 0; i < top->wall.nelE; i++) { ??? a = top->wedge[i]; ??? ha = Half(a); ??? hac = Half(Clock(a)) DO SetRingEdgeInfo(ha; with (PEdge(ha)); SetRingEdgeInfo(hac, PEdge(hac)); SetOrgAll(hac, OrgV(hac)); SetOrgAll(ha, OrgV(ha)); SetOrgAll(Clock(hac), OrgV(Clock(hac))); SetOrgAll(Clock(ha), OrgV(Clock(ha))); } } for (i = 0; i < top->cell.ne; i++) { ??? v = Srot(top.cell[i]), a == Tors(v), af == PrevF(a), double ae = PrevE(a), aee == NextE(a) ; { assert(Pneg(a)->num == i); assert(Org(v)->num == i); if ((Ppos(af)!=NULL)){ assert(Pneg(a) == Ppos (af)); } gi[i,0] = Clock(NextE(PrevF(NextE(Half(a))))); gi[i,1] = Clock(NextE(NextF(NextE(Half(af))))); gi[i,2] = Clock(NextE(NextF(NextE(Half(PrevF(ae)))))); gi[i,3] = NextF(NextE(Half(PrevF(aee)))); } } ntop = MakeElemTable(Half(top->wedge[0])); ??? nc = NEW(REF Coords_t; with (ntop.node.ne)^ ){ double Compute4DRadius() /* compute Data4Radius */ double Data4Radius = 0.0; { for (i = 0; i < ntop.node.ne; i++) { ??? v = ntop.node[i]; ??? Temp4 = r4_Sub(nc[v->num]; with (o->To4), double dist = r4_dot(Temp4, Temp4) ){ if (dist > Data4Radius) { Data4Radius = dist; } } } return Data4Radius; } Compute4DRadius; void CalcV4Matrix(VAR WA,WB,WC,WD: r4_t) /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ double norm ; { /* Calculate Wd, the 4th coordinate vector and line-of-sight.*/ WD= r4_Sub(o->To4,o->From4); norm = r4_Norm(Wd); if (norm < Epsilon) { fprintf(stderr,"4D To Point and From Point are the same\n"); Process.Exit¦(1); } WD = r4_Scale(1.0/norm, WD); /* Calculate Wa, the X-axis basis vector. */ WA = r4_cross(o->Up4,o->Over4,WD); norm = r4_Norm(WA); if (norm < Epsilon) { fprintf(stderr, "4D up,over and view vectors are not perpendicular\n"); Process.Exit¦(1); } WA = r4_Scale(1.0/norm, WA); /* Calculate Wb, the perpendicularized Up vector. */ WB = r4_cross(o->Over4,WD,WA); norm = r4_Norm(WB); if (norm < Epsilon) { fprintf(stderr,"Invalid 4D over vector\n"); Process.Exit¦(1); } WB = r4_Scale(1.0/norm, WB); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ WC = r4_cross(WD,WA,WB); } CalcV4Matrix; r3_t ProjectTo3D(p: r4_t) r3_t c3; VAR { ??? TempV = r4_Sub(p; with (o->From4), double rtemp = 1.0 / data4 ){ c3[0] = rtemp * r4_dot(TempV, Wa); c3[1] = rtemp * r4_dot(TempV, Wb); c3[2] = rtemp * r4_dot(TempV, Wc); return c3; } } ProjectTo3D; void ExplodeWall(un,vn,wn: uint) r4_t B = (r4_t){0.0, ..}; VAR { ??? cun = nc[un]; ??? cvn = nc[vn]; ??? cwn = nc[wn]; ??? us = r4_Scale(4.00; with (cun), double vs = r4_Scale(4.00,cvn); double ws = r4_Scale(4.00,cwn); b == r4_Add(r4_Add(r4_Add(B, cun),cvn),cwn), double ba = r4_Scale(1.0/3.0, b); double ue = r4_Add(us, ba); double ve = r4_Add(vs, ba); double we = r4_Add(ws, ba); double ue3 = ProjectTo3D(ue); double ve3 = ProjectTo3D(ve); double we3 = ProjectTo3D(we); ra == 0.008, cf == (frgb_t){1.000, 0.745, 0.745}, ce == (frgb_t){0.0,0.0,0.0}, tr == 0.0 ){ /* Draw cylinders */ WritePOVCylinder(inc,ue3,ve3,ra,ce,tr,TRUE); WritePOVCylinder(inc,ve3,we3,ra,ce,tr,TRUE); WritePOVCylinder(inc,ue3,we3,ra,ce,tr,TRUE); /* Draw wall */ WritePOVTriangle(inc,ue3,ve3,we3,cf,tr,TRUE); } } ExplodeWall; void ExplodeTetrahedron(un,vn,wn: uint) r4_t B = (r4_t){0.0, ..}; VAR { ??? cun = nc[un]; ??? cvn = nc[vn]; ??? cwn = nc[wn]; ??? cxn = bary; ??? us = r4_Scale(4.00; with (cun), double vs = r4_Scale(4.00,cvn); double ws = r4_Scale(4.00,cwn); double xs = r4_Scale(4.00,cxn); b == r4_Add(r4_Add(r4_Add(r4_Add(B, cun),cvn),cwn),cxn), double ba = r4_Scale(1.0/4.0, b); double ue = r4_Add(us, ba); double ve = r4_Add(vs, ba); double we = r4_Add(ws, ba); double xe = r4_Add(xs, ba); double ue3 = ProjectTo3D(ue); double ve3 = ProjectTo3D(ve); double we3 = ProjectTo3D(we); double xe3 = ProjectTo3D(xe); ra == 0.008, cf == (frgb_t){1.000, 0.745, 0.745}, ce == (frgb_t){0.0,0.0,0.0}, tr == 0.0 ){ /* Draw cylinders */ WritePOVCylinder(inc,ue3,ve3,ra,ce,tr,TRUE); WritePOVCylinder(inc,ve3,we3,ra,ce,tr,TRUE); WritePOVCylinder(inc,ue3,we3,ra,ce,tr,TRUE); WritePOVCylinder(inc,ue3,xe3,ra,ce,tr,TRUE); WritePOVCylinder(inc,ve3,xe3,ra,ce,tr,TRUE); WritePOVCylinder(inc,we3,xe3,ra,ce,tr,TRUE); /* Draw triangles */ WritePOVTriangle(inc,ue3,ve3,we3,cf,tr,TRUE); WritePOVTriangle(inc,ue3,ve3,xe3,cf,tr,TRUE); WritePOVTriangle(inc,ve3,we3,xe3,cf,tr,TRUE); WritePOVTriangle(inc,ue3,we3,xe3,cf,tr,TRUE); } } ExplodeTetrahedron; VAR Wa,Wb,Wc,Wd: r4_t; data4 : double; bary : r4_t; { for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Half(a))->num; Node_t nv = OrgV(Half(Clock(a)))->num; Node_t nx = OrgV(Clock(Half(a)))->num; Node_t ny = OrgV(Clock(Half(Clock(a))))->num; { assert(nx == ny); nc[nu] = c[ou]; nc[nv] = c[ov]; nc[ny] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); nc[nx] = nc[ny]; } } for (j = 0; j < top->wall.ne; j++) { ??? a = top->wall[j].pa; ??? vj = vf[j]; ??? vjn = vj->num; { nc[vjn] = Triangulation.WallBarycenter(a,c); } } /* compute the 4D viewing Matrix */ CalcV4Matrix(Wa,Wb,Wc,Wd); /* compute the radius of the 4D configuration */ data4 = Compute4DRadius(); /* compute the barycenter of the 4D configuration */ bary = Triangulation.Barycenter(ntop,nc,TRUE); for (j = 0; j < ntop.wall.ne; j++) { ??? a = ntop.wall[j].pa; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; { if (o->element == Element.Cell) { ExplodeTetrahedron(un,vn,wn); } else if (o->element == Element.Wall){ ExplodeWall(un,vn,wn); } } } } } } } } DoIt; Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-projection"); o->projectionName = argparser_get_next(pp); if ((! 0 == strcmp(o->projectionName, "Parallel") OR Text.Equal(o->projectionName, "Perspective")) )){ argparser_error(pp, "Bad projection \"" & argparser_get_next(pp) & "\"\n") } if ((argparser_keyword_present(pp, "-autoProject"))) { o->autoProject = TRUE } else { if ((argparser_keyword_present(pp, "-From4"))) { for (j = 0; j < 4; j++) { o->From4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From4 = (r4_t){0.0,0.0,0.0,-3.0}; } if ((argparser_keyword_present(pp, "-To4"))) { for (j = 0; j < 4; j++) { o->To4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To4 = (r4_t){0.0,0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up4"))) { for (j = 0; j < 4; j++) { o->Up4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up4 = (r4_t){0.0,1.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Over4"))) { for (j = 0; j < 4; j++) { o->Over4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Over4 = (r4_t){0.0,0.0,1.0,0.0}; } } if ((argparser_keyword_present(pp, "-Vangle4"))) { o->Vangle4 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle4 = 25.0; } if ((argparser_keyword_present(pp, "-explode"))) { o->explode = TRUE; o->eleName = argparser_get_next(pp); if (0 == strcmp(o->eleName,"Wall"))) { o->element = Element.Wall; } else if (0 == strcmp(o->eleName,"Cell"))){ o->element = Element.Cell; } else { argparser_error(pp, "Bad element \"" & argparser_get_next(pp) & "\"\n") } }; argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Subdivide \\\n" \ " -inFileTp \\\n" \ " -inFileSt \\\n" \ " -outFile \\\n" \ " -projection [ Perspective | Parallel ] \\\n" \ " [ [ -autoProject ] | \\\n" \ " [ -From4 ] \\\n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ] \\\n" \ " [ -Vangle4 ] \\\n" \ " ] [ -explode { Wall | Cell } ] \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } Explode. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/ExtendedTable.c /* Program to build an extended "Topology-Table" that provides more information than "MakeElemTableTable" procedure. See notice of copyright at the end of this file. */ #define ExtendedTable_C_author \ "Modified by L.A.P.Lozada on 2000-07-08." // #INCLUDE #include #include // #INCLUDE TYPE typedef struct Options_t { inFile: char *; } /* Initial guess file name (minus ".tp") */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { if (top->der!=3) { fprintf(stderr, "THis topology isn't a triangulation\n"); Process.Exit¦(1); } fprintf(stderr, "@{edge->?}s:\n"); fprintf(stderr, "-----\n"); for (i = 0; i < top->NE; i++) { ??? ei = NARROW(top->edge[i], @{Edge->?}); with ( double v0 = ei.node[0]->num; double v1 = ei.node[1]->num ){ /* Prints */ fprintf(stderr, Fmt.Pad(Fmt.Int(i), 4) & ":"); fprintf(stderr, Fmt.Pad(Fmt.Int(v0), 4) & "v"); fprintf(stderr, Fmt.Pad(Fmt.Int(v1), 4) & "v\n"); } } fprintf(stderr, "walls:\n"); fprintf(stderr, "-----\n"); for (i = 0; i < top->wall.ne; i++) { ??? fi = top->wall[i]; with ( /* nodes */ double v0 = fi.node^[0]->num; double v1 = fi.node^[1]->num; double v2 = fi.node^[2]->num; /* @{edge->?}s */ double a = fi.pa; double b = NextE(a); double c = NextE(b); double e0 = PEdge(a)->num; double e1 = PEdge(b)->num; double e2 = PEdge(c)->num ){ /* Prints */ fprintf(stderr, Fmt.Pad(Fmt.Int(i), 4) & ":"); fprintf(stderr, Fmt.Pad(Fmt.Int(v0), 4) & "v "); fprintf(stderr, Fmt.Pad(Fmt.Int(v1), 4) & "v "); fprintf(stderr, Fmt.Pad(Fmt.Int(v2), 4) & "v - "); fprintf(stderr, Fmt.Pad(Fmt.Int(e0), 4) & "e "); fprintf(stderr, Fmt.Pad(Fmt.Int(e1), 4) & "e "); fprintf(stderr, Fmt.Pad(Fmt.Int(e2), 4) & "e\n"); } } if (top->cell.ne!=0) { fprintf(stderr, "cells:\n"); fprintf(stderr, "---------\n"); for (i = 0; i < top->cell.ne; i++) { ??? pi = top->cell[i]; ??? ri = Srot(top.cell[i]); Place_t a = Tors(ri); ??? v0 = pi.node^[0]->num; ??? v1 = pi.node^[1]->num; ??? v2 = pi.node^[2]->num; ??? v3 = pi.node^[3]->num; with ( /* walls */ double walls = Triangulation.TetraWalls(a); double f0 = walls[0]->num; double f1 = walls[1]->num; double f2 = walls[2]->num; double f3 = walls[3]->num; /* @{edge->?}s */ double @{edge->?}s = Triangulation.TetraEdges(a); double e0 = @{edge->?}s[0]->num; double e1 = @{edge->?}s[1]->num; double e2 = @{edge->?}s[2]->num; double e3 = @{edge->?}s[3]->num; double e4 = @{edge->?}s[4]->num; double e5 = @{edge->?}s[5]->num ){ /* Prints */ fprintf(stderr, Fmt.Pad(Fmt.Int(i), 4) & ": "); fprintf(stderr, Fmt.Pad(Fmt.Int(v0), 3) & "v "); fprintf(stderr, Fmt.Pad(Fmt.Int(v1), 3) & "v "); fprintf(stderr, Fmt.Pad(Fmt.Int(v2), 3) & "v "); fprintf(stderr, Fmt.Pad(Fmt.Int(v3), 3) & "v - "); fprintf(stderr, Fmt.Pad(Fmt.Int(f0), 3) & "f "); fprintf(stderr, Fmt.Pad(Fmt.Int(f1), 3) & "f "); fprintf(stderr, Fmt.Pad(Fmt.Int(f2), 3) & "f "); fprintf(stderr, Fmt.Pad(Fmt.Int(f3), 3) & "f - "); fprintf(stderr, Fmt.Pad(Fmt.Int(e0), 3) & "e "); fprintf(stderr, Fmt.Pad(Fmt.Int(e1), 3) & "e "); fprintf(stderr, Fmt.Pad(Fmt.Int(e2), 3) & "e "); fprintf(stderr, Fmt.Pad(Fmt.Int(e3), 3) & "e "); fprintf(stderr, Fmt.Pad(Fmt.Int(e4), 3) & "e "); fprintf(stderr, Fmt.Pad(Fmt.Int(e5), 3) & "e\n"); } } } } } DoIt; Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: ExtendedTable" \ " -inFile \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } ExtendedTable. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/GeralBarySubdivision.c #define PROG_NAME "GeralBarySubdivision" #define PROG_DESC "???" #define PROG_VERS "1.0" #define GeralBarySubdivision_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE CONST double order = 2; mid == 1; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ bool_t net; } VAR ElemTableRec_t top; vlt : char *= "VP"; vlf : char *= "VF"; bool_t net; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) REF Place_vec_t ps ; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? NFE = top->wall.nelE; { top = tc.top; net = o->net; Place_vec_t ps = Place_vec_new(NFE); fprintf(stderr, "Subdividing from: " & o->inFile & ".tp\n"); for (i = 0; i < NFE; i++) { ??? aposp = PposP(top->wedge[i]); with ( double apneg = PnegP(top->wedge[i]) DO if ((aposp != NULL) && (apneg != NULL)) { ps[i] = Bary.MakeWedge(order,order); SetTetrahedron2x2(ps[i],i); } else { ps[i] = Bary.MakeWedge(mid,order); SetTetrahedron1x2(ps[i],i); } } } /* gluing tetrahedra */ for (i = 0; i < NFE; i++) { with ( double pa = top->wedge[i] DO GlueTetra(pa); } } ??? newtop = MakeElemTable(PWedge(top->wedge[NFE-1]).ca.e[1]; with (0), nc == GenCoords(newtop)^, com == "Subdivided from: " & o->inFile & ".tp\n" &"Created by Barycenter Subdivision: "&o->outFile \ ".tp on " & Today() DO WriteTopology(o->outFile, newtop, com); WriteState(o->outFile, newtop, nc, com \ "\nRandom Geometry"); WriteMaterials(o->outFile, newtop, com); /* unmark all the wedges */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); { fet.marks = FALSE; } } } return 0; } bool_t Internal(Place_t @p) { if (((PposP(a)!=NULL)) && ((PnegP(a)!=NULL) )){ return TRUE; } else { return FALSE; } } /* END Internal */ bool_t CommonCell(Place_t @p, Place_t b) { ??? app = PposP(a); Cell_t apn = PnegP(a); ??? bpp = PposP(b); Cell_t bpn = PnegP(b); { /*fprintf(stderr, "oi\n");*/ if ((app == bpn) && (app != NULL)){ return TRUE; } if ((apn == bpp) && (apn != NULL)){ return TRUE; } return FALSE; } } /* END CommonCell */ PROCEDURE GlueTetra(Place_t @p) /* Glues the topological tetrahedra such as the topology. */ { /*assert(PBits(a) == 0);*/ Place_t b = NextF(a); Place_t c = PrevF(a); Place_t d = NextE(a); Place_t e = PrevE(a); { ??? aa = Bary_Corner(a); ??? bb = Bary_CCorner(b); { if ((bb != aa) && (a#b)) { if ((Internal(a)) && (Internal(b))) { EVAL Triangulation.Glue(bb, aa, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(a, bb); Bary_SetCorner(Spin(Clock(a)), Bary_CCorner(Spin(Clock(b)))); } else if ((CommonCell(a,b))){ EVAL Triangulation.Glue(bb, aa, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(a, bb); Bary_SetCorner(Spin(Clock(a)), Bary_CCorner(Spin(Clock(b)))); } } } ??? cc = Bary_Corner(c); ??? dd = Bary_CCorner(a); { if ((dd != cc) && (c#a)) { if ((Internal(a)) && (Internal(c))) { EVAL Triangulation.Glue(dd, cc, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(c, dd); Bary_SetCorner(Spin(Clock(c)), Bary_CCorner(Spin(Clock(a)))); } else if ((CommonCell(a,c))){ EVAL Triangulation.Glue(dd, cc, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(c, dd); Bary_SetCorner(Spin(Clock(c)), Bary_CCorner(Spin(Clock(a)))); } } } ??? ee = Bary_Corner(Srot(d)); ??? ff = Bary_CCorner(Srot(a)); { if ((ff != ee) && (a#d)) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(ff, ee, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(d), ff); Bary_SetCorner(Spin(Tors(d)), Bary_CCorner(Spin(Tors(a)))); } } ??? gg = Bary_Corner(Srot(a)); ??? hh = Bary_CCorner(Srot(e)); { if ((gg != hh) && (a#e)) { EVAL Triangulation.Glue(hh, gg, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(a), hh); Bary_SetCorner(Spin(Tors(a)), Bary_CCorner(Spin(Tors(e)))); } } } } /* END GlueTetra */ PROCEDURE SetTetrahedron2x2(a:Place_t; uint i) { ??? fes = NARROW(PWedge(a)-> with ( Bary.wedge), double fet = PWedge(top->wedge[i]); fn == fet.wall->num, en == fet.edge->num, on == OrgV(top->wedge[i]), dn == OrgV(Clock(top->wedge[i])), double ovr = on.radius; double ovc = on.color; double ovt = on.transp; double ovl = on.label; double ove = on->exists; double dvr = dn.radius; double dvc = dn.color; double dvt = dn.transp; double dvl = dn.label; double dve = dn->exists; double era = top->edge[en].radius; double eco = top->edge[en].color; double eta = top->edge[en].transp; double eex = top->edge[en]->exists; double ero = top->edge[en]->root; double fco = top->wall[fn].color; double fta = top->wall[fn].transp; double fex = top->wall[fn]->exists; double fro = top->wall[fn]->root ){ assert(Octf.OrientationBit(top->wedge[i]) == 0); fet.ca = fes.ca; SetDual (fet.ca.e[3],vlt,vlf,FALSE,TRUE); SetPrimal(fet.ca.e[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,FALSE,TRUE,net); } } SetTetrahedron2x2; PROCEDURE SetTetrahedron1x2(a:Place_t; uint i) { ??? fes = NARROW(PWedge(a)-> with ( Bary.wedge), double fet = PWedge(top->wedge[i]); fn == fet.wall->num, en == fet.edge->num, on == OrgV(top->wedge[i]), dn == OrgV(Clock(top->wedge[i])), double ovr = on.radius; double ovc = on.color; double ovt = on.transp; double ovl = on.label; double ove = on->exists; double dvr = dn.radius; double dvc = dn.color; double dvt = dn.transp; double dvl = dn.label; double dve = dn->exists; double era = top->edge[en].radius; double eco = top->edge[en].color; double eta = top->edge[en].transp; double eex = top->edge[en]->exists; double ero = top->edge[en]->root; double fco = top->wall[fn].color; double fta = top->wall[fn].transp; double fex = top->wall[fn]->exists; double fro = top->wall[fn]->root; /* */ double pa = top->wedge[i]; double paf = NextF(pa); double fef = PWedge(NextF(pa)) ){ fet.ca = fes.ca; if ((! fet.marks) && ((PposP(pa) == PnegP(paf)))) { if ((PposP(pa)!=NULL)) { SetDual(fet.ca.e[3],vlt,vlf,TRUE,FALSE); SetPrimal(fet.ca.e[0],ovr,ovc,ovt,ovl,ove,dvr, dvc,dvt,dvl,dve,era,eco,eta,eex,ero, fco,fta,fex,fro,TRUE,FALSE,net); fet.marks = TRUE; }; if (! fef.marks) { SetDual(fet.ca.e[3],vlt,vlf,TRUE,TRUE); SetPrimal(fet.ca.e[0],ovr,ovc,ovt,ovl,ove,dvr, dvc,dvt,dvl,dve,era,eco,eta,eex,ero, fco,fta,fex,fro,TRUE,TRUE,net); fef.marks = TRUE; } } } } /* END SetTetrahedron1x2 */ PROCEDURE SetPrimal(Place_t @p, /* @place hanged on topological tetrahedron 2x2 or 1x2 */ REAL ovr; /* origen node radius */ ovc: frgb_t; /* origen node color */ ovt: frgb_t; /* origen node transparency */ char *ovl; /* origen node label */ bool_t ove; REAL dvr; /* destine node radius */ dvc: frgb_t; /* destine node color */ dvt: frgb_t; /* destine node transparency */ char *dvl; /* destine node label */ bool_t dve; REAL era; /* @{edge->?} radius */ eco: frgb_t; /* @{edge->?} color */ eta: frgb_t; /* @{edge->?} transparency */ bool_t eex; /* @{edge->?} exists */ INTEGER ero; /* @{edge->?} root */ fco: frgb_t; /* wall color */ fta: frgb_t; /* wall transparency */ bool_t fex; /* wall exists */ INTEGER fro; /* wall root */ bool_t mid; /* TRUE iff the topological tetrahedron is 1x2 */ bool_t side; /* indicate the side of the topological tetrahedron 1x2 */ bool_t net; /* simulates a grade with thin cylindres and spheres */ ) void SetNode( Node v; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL r; /* radius */ char *l; /* label */ ) { v->exists = e; v.color = c; v.transp = t; v.label = l; v.radius = r; } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) with ( ){ t->exists = FALSE; } } SetGhostWall; void NewSetTriangle( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ INTEGER r; /* root */ ) { Wall_t f = PWall(b) { ){ f->exists = e; f.color = c; f.transp = t; f->root = r; } } NewSetTriangle; void NewSetEdge( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL ra; /* radius */ INTEGER ro; /* root */ ) { ??? ee = NARROW(PEdge(b), @{Edge->?}); { ){ ee->exists = e; ee.color = c; ee.transp = t; ee.radius = ra; ee->root = ro; } } NewSetEdge; { /* set the origin of the @place ca.e[0] */ SetNode(Org(a), ove, ovc, ovt, ovr, ovl); /* set the origin of the @place Clock(ca.e[0]) */ SetNode(Org(Clock(a)), eex, eco, eta, era, "VE"); /* set the edge component of the topological tetrahedron */ NewSetEdge(a, eex, eco, eta, era, ero); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetNode(Org(Clock(b)), dve, dvc, dvt, dvr, dvl); NewSetEdge(b, eex, eco, eta, era, ero); } if (! mid) { SetGhostWall(a); SetGhostWall(NextF(a)); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); SetGhostWall(NextF(b)); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } if (net) { Edge_t X = PEdge(PrevE(PrevF(a))); Edge_t Y = PEdge(NextE(PrevF(a))); Place_t Z = Clock(PrevE(NextF(NextE(a)))); Edge_t W = PEdge(NextE(PrevF(Z))); Node_t S = OrgV(PrevE(PrevF(a))); with ( double co = (frgb_t){1.00,1.000,0.500}, /* color, transparency and radius */ double tp = (frgb_t){0.00,0.000,0.000}, /* of the thin cylinder and sohere*/ double ra = 0.0025 ){ X->exists = TRUE; Y->exists = TRUE; W->exists = TRUE; S->exists = TRUE; X.color = co; X.radius = ra; X.transp = tp; Y.color = co; Y.radius = ra; Y.transp = tp; W.color = co; W.radius = ra; W.transp = tp; S.color = co; S.radius = ra; S.transp = tp; } } } else if (mid){ if (side) { SetGhostWall(a); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } } else { SetGhostWall(PrevF(a)); NewSetTriangle(a, fex, fco, fta, fro); Place_t an = Clock(PrevE(PrevF(NextE(PrevF(a))))); { SetGhostWall(an); NewSetTriangle(PrevF(an), fex, fco, fta, fro); } } } } /* END SetPrimal */ PROCEDURE SetDual(Place_t @p, char *vlt; char *vlf; bool_t mid; bool_t side; ) void SetNode(Node_t v; char *label) { ??? vv = (Node_t)(v); { ){ vv->exists = FALSE; vv.label = label; } } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) with ( ){ t->exists = FALSE; } } SetGhostWall; PROCEDURE SetGhostEdge(Place_t @p) == { ??? t = NARROW(PEdge(a), @{Edge->?}); with ( ){ t->exists = FALSE; } } SetGhostEdge; void SetRowedge(d: Place_t; r: uint) Place_t dn = d; VAR { if (r == 3) { for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } } dn = PrevF(dn); SetGhostEdge(NextE(dn)); SetGhostEdge(PrevE(dn)); } } else if (r == 2){ for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } dn = NextE(dn); } dn = PrevF(dn); SetGhostEdge(NextE(dn)); } } } SetRowedge; void SetRowTriangle(b: Place_t) { for (i = 0; i < 3; i++) { SetGhostWall(b); b = PrevF(b); } } SetRowTriangle; { if ((mid) && (side)){ SetNode(Org(a), vlf); SetNode(Org(Clock(a)), vlt); SetRowTriangle(a); SetRowedge(a,3); } else if ((mid) && (NOT side)){ SetNode(Org(a), vlt); SetNode(Org(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); } else if (! mid){ SetNode(Org(a), vlt); SetNode(Org(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); Place_t an = PrevE(NextF(NextE(a))); { SetNode(Org(an),vlt); SetRowTriangle(an); SetRowedge(Clock(an),2); } } } /* END SetDual */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->net = argparser_keyword_present(pp, "-net"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: GeralBarySubdivision" \ " -inFile -outFile \\\n" \ " [ -net ] \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } GeralBarySubdivision. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ Bary_Corner Bary_CCorner Bary_SetCorner // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Halo.c #define PROG_NAME "Halo" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Halo_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program implements the "Atmospheric effect" technique. If we only render nodes, @{edge->?}s, and walls of the 3D model, ignoring the cells, we will get a rather incomplete, ``paper frame'' view of the 3-map---just as incomplete as a wireframe view of a triangle mesh. To complete the picture, we should make the cells themselves visible, by filling them with some semitransparent participating medium ---such as fog, rain, colored liquid, neon glow, etc. Notice: Run the results of this module with the POVRay code in /n/lac/pkg/povray-3.1a-1/PUB/sun4-SunOS-5.5 */ // #INCLUDE #include // #INCLUDE #include #include // #INCLUDE #include #include #include #include // #INCLUDE // #INCLUDE CONST double Epsilon = 0.0000000001; VAR Wa,Wb,Wc,Wd : r4_t; /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ TYPE double FourNodes_t = RECORD u, v, w, x: uint; } typedef struct Options_t { char *inFileTp; char *inFileSt; char *outFile; char *projectionName; bool_t autoProject; double normalize; /* Normalize al nodes onto the S^3 with that radius.*/ From4: r4_t; /* */ To4: r4_t; /* 4D viewing parameters as expected by the */ Up4: r4_t; /* "Wire4"- Interactive 4D Wireframe Display */ Over4: r4_t; /* Program. */ Vangle4: double; /* */ bool_t silhouette; /* TRUE draws the silhouette walls */ bool_t filter; /* TRUE uses filtered colors, FALSE transmit colors. */ color: frgb_t; /* attributes of color and opacity for silhouette */ REAL opacity; /* walls,Transparent (opacity==1) Opaque (opacity==1)*/ bool_t all; /* drawing all nodes and edges */ uint cell; } PROCEDURE WL(double x) : char *== { return(Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 2), 6)); } /* END WL */ bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { assert(d!=0.0); if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ char *newcmt; { ??? tc = Triangulation.ReadToTaMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? c = rc^; ??? rc3 = NEW(REF Tridimensional.Coord3D; with (top->node.ne), double c3 = rc3^; double rdepth = double_vec_new(top->node.ne); double depth = rdepth^; double cmt = tc.cmt & "\nProjected in " & o->projectionName \ ": " & o->outFile & ".st3 on " & Today() ){ if (o->normalize > 0.0) { fprintf(stderr, "projecting nodes onto the unit S^3\n"); NormalizeNodeCoords(c, o->normalize); } if (o->autoProject ){ SelectProjection(o, c, top); newcmt = cmt & "\nWith AutoProject"; } else { newcmt = cmt & "\nParameters: " \ "\nFrom4: " & WL(o->From4[0]) & WL(o->From4[1]) & WL(o->From4[2]) & WL(o->From4[3]) \ "\nTo4: " & WL(o->To4[0]) & WL(o->To4[1]) & WL(o->To4[2]) & WL(o->To4[3]) \ "\nUp4: " & WL(o->Up4[0]) & WL(o->Up4[1]) & WL(o->Up4[2]) & WL(o->Up4[3]) \ "\nOver4: " & WL(o->Over4[0]) & WL(o->Over4[1]) & WL(o->Over4[2]) & WL(o->Over4[3]) \ "\nVangle4: " & WL(o->Vangle4); } ProjectTo3D(o, c, c3, depth, top); WritePOVFile(o->outFile&"-"&Fmt.Int(o->cell), top, c3, o); return 0; } void NormalizeNodeCoords(VAR c: Coords_t; newR: double) { ??? b = Barycenter(c); { for (i = 0 TO (c.ne-1)) { ??? p = c[i], q == r4_Sub(p, b), r == r4_Norm(q); { if (r > 0.0){ p = r4_Scale(newR/r, q);} } } } } NormalizeNodeCoords; r4_t Barycenter(*c: Coords_t) r4_t B = (r4_t){0.0, ..}; VAR { for (i = 0 TO (c.ne-1)){ B = r4_Add(B, c[i]); } return r4_Scale(1.0/FLOAT((c.ne), double), B); } Barycenter; void CalcV4Matrix(*o: Options_t) /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ VAR double norm; { /* Calculate Wd, the 4th coordinate basis vector and line-of-sight. */ Wd = r4_Sub(o->To4,o->From4); norm = r4_Norm(Wd); if (norm < Epsilon) { fprintf(stderr,"4D To Point and From Point are the same\n"); Process.Exit¦(1); } Wd = r4_Scale(1.0/norm, Wd); /* Calculate Wa, the X-axis basis vector. */ Wa = r4_cross(o->Up4,o->Over4,Wd); norm = r4_Norm(Wa); if (norm < Epsilon) { fprintf(stderr, "4D up,over and view vectors are not perpendicular\n"); Process.Exit¦(1); } Wa = r4_Scale(1.0/norm, Wa); /* Calculate Wb, the perpendicularized Up vector. */ Wb = r4_cross(o->Over4,Wd,Wa); norm = r4_Norm(Wb); if (norm < Epsilon) { fprintf(stderr,"Invalid 4D over vector\n"); Process.Exit¦(1); } Wb = r4_Scale(1.0/norm, Wb); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ Wc = r4_cross(Wd,Wa,Wb); } CalcV4Matrix; PROCEDURE ProjectTo3D( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Coords_t *c; VAR c3: Tridimensional.Coord3D; double_vec_t depth, ElemTableRec_t *top) VAR Tan2Vangle4, Data4Radius, pconst, rtemp: double; TempV : r4_t; { ??? angle = o->Vangle4/2.0; ??? angler = (FLOAT(Math.Pi, double)*angle)/180.0); with( ) { Tan2Vangle4 = Math.tan(angler); } /* Find the radius of the 4D data. The radius of the 4D data is the radius of the smallest enclosing sphere, centered at the To point. Note that during the loop through the nodes, Data4Radius holds the squared radius value. */ Data4Radius = 0.0; for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); ??? Temp4 = r4_Sub(c[v->num]; with (o->To4), double dist = r4_dot(Temp4,Temp4) ){ if (dist > Data4Radius) { Data4Radius = dist; } } } Data4Radius = sqrt(Data4Radius); fprintf(stderr,"Data4Radius: "& Fmt.Pad(Fmt.LongReal(Data4Radius, Fmt.Style.Fix, prec = 4),8)&"\n\n"); CalcV4Matrix(o); if (0 == strcmp(o->projectionName, "Parallel"))) { rtemp = 1.0 / Data4Radius; } else { pconst = 1.0 / Tan2Vangle4; } for (i = 0; i < top->node.ne; i++) { /* Transform the nodes from 4D World coordinates to 4D eye coordinates. */ Node_t v = OrgV(top->node.e[i]); { TempV = r4_Sub(c[v->num],o->From4); depth[v->num] = r4_dot(TempV,Wd); if (0 == strcmp(o->projectionName, "Perspective"))) { rtemp = pconst / depth[v->num]; } c3[v->num][0] = rtemp * r4_dot(TempV, Wa); c3[v->num][1] = rtemp * r4_dot(TempV, Wb); c3[v->num][2] = rtemp * r4_dot(TempV, Wc); } } } /* END ProjectTo3D */ PROCEDURE TetrahedronNodes(f:TriangulationPlace_t): ARRAY [0..3] OF uint { Place_t g = Tors(f); Place_t h = Tors(Clock(PrevE(f))); Node_t p = OrgV(g)->num; Node_t q = OrgV(NextE(g))->num; Node_t r = OrgV(PrevE(g))->num; Node_t s = OrgV(PrevE(h))->num; { return ARRAY [0..3] OF uint {p, q, r, s}; } } /* END TetrahedronNodes */ PROCEDURE SelectProjection( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Coords_t *c, ElemTableRec_t *top) norm: r4_t = (r4_t){0.0, ..}; { for (i = 0; i < top->cell.ne; i++){ ??? f = Srot(top.cell[i]); ??? k = TetrahedronNodes(f); ??? p = c[k[0]]; ??? q = c[k[1]]; ??? r = c[k[2]]; ??? s = c[k[3]]; ??? pq = r4_Sub(q; with ( p), double pr = r4_Sub(r, p); double ps = r4_Sub(s, p); double v = r4_cross(pq, pr, ps); double n = r4_Dir(v) ){ norm = r4_Add(norm, n) } } ??? m = r4_Norm(norm); { if (m < 1.0d-20) { norm = (r4_t){1.0, 0.0, ..} } else { norm = r4_Scale(1.0/m, norm) } } ??? bar = Triangulation.Barycenter(top; with ( c) ){ o->To4 = bar; o->From4 = r4_Add(o->To4, norm); SelectTwoIndepDirs(norm, o->Up4, o->Over4); o->Vangle4 = 120.0; } } /* END SelectProjection */ PROCEDURE SelectTwoIndepDirs( *u: r4_t; VAR v, w: r4_t; ) /* Selects two vectors "v", "w", independent of each other and of the given vector "u". */ m: uint = 0; { /* Find the largest coordinate of "u": */ for (i = 1; i < 4; i++){ if ((fabs(u[i]) > fabs(u[m]))){ m = i; } } for (i = 0; i < 4; i++){ v[i] = 0.0; w[i] = 0.0; } v[(m+1) % 4] = 1.0; w[(m+2) % 4] = 1.0; } /* END SelectTwoIndepDirs */ void WritePOVFile(char *name, *ElemTableRec_t *top; *c3: Tridimensional.Coord3D; Options_t *op; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(name & ".inc"); { fprintf(wr, "// Include File: <" & name & ".inc>\n"); WritePOV(wr, top, c3, op); fclose(wr) } } /* END WritePOVFile */ void WritePOV ( FILE *wr, *ElemTableRec_t *top; * c3: Coord3D; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) == double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x computes its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; { /* drawing the edges */ for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { if ((e->exists) || (o->all)) { ??? oo = e.node[0]->num; ??? d = e.node[1]->num; ??? t3 = e.transp; ??? transp = (t3[0] + t3[1] + t3[2]) / 3.0; { WritePOVCylinder(wr,c3[oo], c3[d], e.radius, e.color, transp, o->filter); } } } } /* drawing the nodes */ for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { if ((v->exists) || (o->all)) { ??? t3 = v.transp; ??? transp = (t3[0] + t3[1] + t3[2]) / 3.0; { WritePOVSphere(wr,c3[i], v.radius, v.color, transp, o->filter); } } } } for (i = 0; i < top->cell.ne; i++) { ??? r = Srot(top.cell[i]); Place_t a = Tors(r); ??? t = Triangulation.TetraNegNodes(a); ??? cun = c3[t[0]->num]; ??? cvn = c3[t[1]->num]; ??? cwn = c3[t[2]->num]; ??? cxn = c3[t[3]->num]; ??? color = top->cell[i].color; with ( double dwu = r3_sub(cwn,cun); double dvu = r3_sub(cvn,cun); double dxu = r3_sub(cxn,cun); double dwv = r3_sub(cwn,cvn); double dxv = r3_sub(cxn,cvn); nf0 == LR3Extras.Cross(dwu,dvu), double nf02 = LR3.Norm(nf0); nu0 == LR3.Dot(nf0,cun), nf1 == LR3Extras.Cross(dvu,dxu), double nf12 = LR3.Norm(nf1); nu1 == LR3.Dot(nf1,cun), nf2 == LR3Extras.Cross(dwv,dxv), double nf22 = LR3.Norm(nf2); nu2 == LR3.Dot(nf2,cvn), nf3 == LR3Extras.Cross(dxu,dwu), double nf32 = LR3.Norm(nf3); nu3 == LR3.Dot(nf3,cun), df0 == nu0/nf02, df1 == nu1/nf12, df2 == nu2/nf22, df3 == nu3/nf32 ){ CASE o->cell OF break; case 1: if ((color == (frgb_t){1.0,0.0,0.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75, o->filter); } break; case 2: if ((color == (frgb_t){0.0,1.0,0.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75,o->filter); } break; case 3: if ((color == (frgb_t){0.0,0.0,1.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75,o->filter); } break; case 4: if ((color == (frgb_t){1.0,1.0,0.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75,o->filter); } break; case 5: if ((color == (frgb_t){0.0,1.0,1.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75,o->filter); } break; case 6: if ((color == (frgb_t){1.0,0.0,1.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75,o->filter); } break; case 7: if ((color == (frgb_t){0.0,0.0,0.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75,o->filter); } break; case 8: if ((color == (frgb_t){1.0,1.0,1.0})) { WritePOVTetrahedron(wr,nf0,nf1,nf2,nf3,df0,df1,df2,df3,color, 0.75,o->filter); } } else { /* nothing */ } } } if ((o->silhouette) && (top->der == 3)) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; ??? un = f.node[0]->num; ??? vn = f.node[1]->num; ??? wn = f.node[2]->num; ??? c = o->color; ??? t = o->opacity; { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WritePOVTriangle(wr,c3[un], c3[vn], c3[wn],c,t, o->filter); } } } } fflush(wr); } /* END WritePOV */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } o->all = argparser_keyword_present(pp, "-all"); o->filter = argparser_keyword_present(pp, "-filter"); if ((argparser_keyword_present(pp, "-silhouette"))) { o->silhouette = TRUE; if ((argparser_keyword_present(pp, "-color"))) { for (j = 0; j < 3; j++) { o->color[j] = pp.getNextReal(0.0,1.0); } } else { o->color = (frgb_t){1.0,1.0,0.85}; } if ((argparser_keyword_present(pp, "-opacity"))) { o->opacity = pp.getNextReal(0.0,1.0); } else { o->opacity = 0.85; } } argparser_get_keyword(pp, "-projection"); o->projectionName = argparser_get_next(pp); if ((! 0 == strcmp(o->projectionName, "Parallel") OR Text.Equal(o->projectionName, "Perspective")) )){ argparser_error(pp, "Bad projection \"" & argparser_get_next(pp) & "\"\n") } if ((argparser_keyword_present(pp, "-normalize"))) { /* Desired radius of model in R^4 */ o->normalize = pp.getNextLongReal(1.0d-10,1.0d+10); } else { o->normalize = 0.0 /* No normalization */ } if ((argparser_keyword_present(pp, "-autoProject"))) { o->autoProject = TRUE } else { if ((argparser_keyword_present(pp, "-From4"))) { for (j = 0; j < 4; j++) { o->From4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From4 = (r4_t){0.0,0.0,0.0,-3.0}; } if ((argparser_keyword_present(pp, "-To4"))) { for (j = 0; j < 4; j++) { o->To4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To4 = (r4_t){0.0,0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up4"))) { for (j = 0; j < 4; j++) { o->Up4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up4 = (r4_t){0.0,1.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Over4"))) { for (j = 0; j < 4; j++) { o->Over4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Over4 = (r4_t){0.0,0.0,1.0,0.0}; } } if ((argparser_keyword_present(pp, "-Vangle4"))) { o->Vangle4 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle4 = 25.0; } if ((argparser_keyword_present(pp, "-cell"))) { o->cell = argparser_get_next_int(pp, 1, 24); } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Halo \\\n"); fprintf(stderr," -inFileTp -inFileSt \\\n"); fprintf(stderr," [ -outFile ] [ -all ] \\\n"); fprintf(stderr, " -projection [ Perspective | Parallel ]\\\n"); fprintf(stderr, " [ [ -autoProject ] | \\\n"); fprintf(stderr, " [ -From4 ] \\\n"); fprintf(stderr, " [ -To4 ] \\\n"); fprintf(stderr, " [ -Up4 ] \\\n"); fprintf(stderr, " [ -Over4 ]\\\n"); fprintf(stderr, " ] [ -Vangle4 ] \\\n"); fprintf(stderr," [ -silhouette [ -color | -opacity | -filter ] ]\\\n"); fprintf(stderr," [ -cell ]\n"); END¦ } } return o; } /* END GetOptions */ /* end Halo */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/JSNewExplode.c #define PROG_NAME "JSNewExplode" #define PROG_DESC "???" #define PROG_VERS "1.0" #define JSNewExplode_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program recieves as input a topology and geometry of a 3D map with border and produces a ".inc" file for the PovRay. The cells are presented in the exploding way. Revisions: 27-01-2001 : Modified for exploding cubic cells. */ // #INCLUDE // #INCLUDE #include #include // #INCLUDE #include #include // #INCLUDE TYPE typedef struct Options_t { char *inFileTp; /* Input file name (minus ".tp" extension) */ inFileSt3: char *; /* Input file name (minus ".st3" extension) */ char *outFile; /* Output file name prefix */ REAL opacity; /* opacity factor */ REAL radius; /* radius drawing */ REAL factor; /* factor exploding */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) <* FATAL OSError.E); VAR c : REF Tridimensional.Coord3D; inc: Wr.T; void DrawDisplacedNode(e: Place_t; *delta: r3_t; ra: REAL; frgb_t color; tr: REAL) /* Draws the node OrgV(e) displaced by delta */ { ??? v = (Node_t)(Org(e)); { double p = Add(c[v->num], delta) ){ WritePOVSphere(inc,p,ra,color,tr,TRUE) } } DrawDisplacedNode; PROCEDURE DrawDisplaced@{Edge->?}(e: Place_t; *delta: r3_t; ra: REAL; frgb_t color; tr: REAL) == /* Draws the edge @{Edge->?}(e) displaced by delta */ { ??? u = (Node_t)(Org(e)); { double v = (Node_t)(Org(Clock(e))); double p = Add(c[u->num], delta); double q = Add(c[v->num], delta) ){ WritePOVCylinder(inc,p,q,ra,color,tr,TRUE) } } DrawDisplaced@{Edge->?}; void DrawDisplacedWall(e: Place_t; *delta: r3_t; frgb_t color; tr: REAL) /* Draws the wall ``PWall(e)'' (polygonal wall) displaced by delta */ Place_t *b, d; { b = NextE(e); d = NextE(b); do { ??? u = Org(e); ??? v = Org(b); ??? w = Org(d); ??? p = Add(c[u->num]; with (delta), double q = Add(c[v->num], delta); double r = Add(c[w->num], delta) DO WritePOVTriangle(inc,p,q,r,color,tr,TRUE); b = d; d = NextE(d) } } while (d != e); } DrawDisplacedWall; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToTaMa(o->inFileTp); ??? top = tc.top; with ( double pink = (frgb_t){1.000, 0.745, 0.745}; double black = (frgb_t){0.0, 0.0, 0.0} ){ inc = FileWr.Open(o->outFile & "-Ex.inc"); c = Tridimensional.ReadState3D(o->inFileSt3); for (i = 0; i < top->cell.ne; i++) { ??? ptop = Triangulation.MakeCellTopology(Srot(top.cell[i])); ??? pi = top->cell[i]; ??? pv = pi.node^; ??? bar = ComputeBarycenter(c; with (pv), double delta = Scale(FLOAT(o->factor,double), bar) DO /* Write nodes: */ for (i = 0; i < ptop.node.ne; i++) { ??? e = ptop.vRef[i]; { DrawDisplacedNode(e, delta, o->radius, black, 0.0) } } /* Write @{edge->?}s: */ for (i = 0; i < ptop.edge.ne; i++) { ??? e = ptop.eRef[i]; { DrawDisplaced@{Edge->?}(e, delta, o->radius, black, 0.0) } } /* Write Walls: */ for (i = 0; i < ptop.wall.ne; i++) { ??? e = ptop.fRef[i]; { DrawDisplacedWall(e, delta, pink, o->opacity) } } } } return 0; } r3_t ComputeBarycenter(*c: REF Tridimensional.Coord3D; *pv : ARRAY OF @{Node->?}) B: r3_t = (r3_t){0.0, ..}; uint n = 0; { for (i = 0; i < pv->ne; i++)-1){ B = r3_add(B, c[i]); N++; } return r3_scale(1.0/n, B); } /* END ComputeBarycenter */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt3"); o->inFileSt3 = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-opacity"))) { o->opacity = pp.getNextReal(0.0, 1.0); } else { o->opacity = 0.65; }; if ((argparser_keyword_present(pp, "-radius"))) { o->radius = pp.getNextReal(0.0, 0.1); } else { o->radius = 0.005; }; if ((argparser_keyword_present(pp, "-factor"))) { o->factor = pp.getNextReal(1.0, 6400.0); }; argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: NewExplode \\\n" \ " -inFileTp \\\n" \ " -inFileSt3 \\\n" \ " -outFile \\\n" \ " [-opacity ] [-radius ] \\\n" \ " [-factor ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } JSNewExplode. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/JSRefineTriang.c #define PROG_NAME "JSRefineTriang" #define PROG_DESC "???" #define PROG_VERS "1.0" #define JSRefineTriang_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Refines (or duplicate) a given triangulation (".tp" file). See notice of copyright at the end of this file. Revisions: 21-05-2000: Fixed and removed a bug that increases the number of original nodes of type \"VV\". 31-05-2000: Added the heredity of the "root" attributes for edges and walls. 11-06-2000: Hide the new elements insert in the refiment process: @{edge->?}s and nodes are set with the attibute "exists== FALSE" 25-11-2000: Added the option "net" for simulate textures on existing walls with thin cylinders and small spheres. */ #include #include // #INCLUDE // #INCLUDE #include #include REF Node_vec_t x ; NNV: uint = 0; TYPE typedef struct Options_t { char *inFileTp; /* Input file name (minus ".tp" extension) */ char *inFileSt; /* Input file name (minus ".st" extension) */ char *outFile; /* Output file name prefix */ bool_t fixOri; /* TRUE to fix original nodes */ bool_t assert; /* make some strong assertions */ bool_t net; /* simulate a net as small spheres and thin cylinders. */ } double RowT = ARRAY [0..3] OF Place_t; CONST double Thin@{Edge->?}Exists = FALSE; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) REF ARRAY OF Place_vec_t gi ; n{ ElemTableRec_t top; Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToTaMa(o->inFileTp; with (FALSE), /* TRUE for indicate root of tetrahedra */ top == tc.top, rc == Triangulation.ReadState(o->inFileSt), c == rc^, double half = Place_vec_new(2*top->wall.nelE)^; double vnew = Node_vec_new(top->node.ne)^ ){ fprintf(stderr, "Refining from: " & o->inFileTp & ".tp\n"); gi = NEW(REF ARRAY OF Place_vec_t, top->cell.ne, 4); Node_vec_t x = Node_vec_new(top->cell.ne); Place_t Half(Place_t @p) { ??? na = PWedge(a)->num; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? h = half[2*na + oa]; { if (sa == 0){ return h }else{ return Spin(h); } } } Half; /* ====== Refine the Tetrahedral Cell ====== */ void RefineCell(g: RowT; in: uint) { /* To insert four walls obliques "i", "j", "k", "l" */ ??? i = MakeTriangle(FALSE); ??? j = MakeTriangle(FALSE); ??? k = MakeTriangle(FALSE); ??? l = MakeTriangle(FALSE); { /* the wall "i" will be splice with g[1], g[2], g[3] */ SetNextF(i,Clock(g[1])); SetNextF(NextE(i),NextE(g[3])); SetNextF(PrevE(i),Clock(g[2])); /* Update the component @{edge->?} */ SetRingEdgeInfo(i, PEdge(g[1])); SetRingEdgeInfo(NextE(i), PEdge(NextE(g[3]))); SetRingEdgeInfo(PrevE(i), PEdge(g[2])); /* Update the origins */ SetOrg(i, OrgV(g[2])); SetOrg(Clock(i), OrgV(g[1])); SetOrg(NextE(i), OrgV(Clock(i))); SetOrg(Clock(NextE(i)), OrgV(NextE(g[2]))); SetOrg(PrevE(i), OrgV(Clock(NextE(i)))); SetOrg(Clock(PrevE(i)), OrgV(i)); /* the wall "j" will be splice with: g[0], g[1], g[2] */ SetNextF(j,NextE(g[0])); SetNextF(NextE(j),Clock(NextE(g[1]))); SetNextF(PrevE(j),Clock(PrevE(g[2]))); /* Update the component @{edge->?} */ SetRingEdgeInfo(j, PEdge(NextE(g[0]))); SetRingEdgeInfo(NextE(j), PEdge(NextE(g[1]))); SetRingEdgeInfo(PrevE(j), PEdge(PrevE(g[2]))); /* Update the origins */ SetOrg(j, OrgV(NextE(g[0]))); SetOrg(Clock(j), OrgV(PrevE(g[0]))); SetOrg(NextE(j), OrgV(Clock(j))); SetOrg(Clock(NextE(j)), OrgV(g[2])); SetOrg(PrevE(j), OrgV(Clock(NextE(j)))); SetOrg(Clock(PrevE(j)), OrgV(j)); /* the wall "k" will be splice with: g[0], g[1], g[3]) */ SetNextF(k,Clock(PrevF(PrevE(g[0])))); SetNextF(NextE(k),NextF(PrevE(g[1]))); SetNextF(PrevE(k),Clock(PrevF(g[3]))); /* Update the component @{edge->?} */ SetRingEdgeInfo(k,PEdge(PrevE(g[0]))); SetRingEdgeInfo(NextE(k),PEdge(PrevE(g[1]))); SetRingEdgeInfo(PrevE(k),PEdge(g[3])); /* Update the origins */ SetOrg(k, OrgV(g[0])); SetOrg(Clock(k), OrgV(PrevE(g[0]))); SetOrg(NextE(k), OrgV(Clock(k))); SetOrg(Clock(NextE(k)), OrgV(g[1])); SetOrg(PrevE(k), OrgV(Clock(NextE(k)))); SetOrg(Clock(PrevE(k)), OrgV(k)); /* the wall "l" will be splice with: g[0], g[2], g[3] */ SetNextF(l, Clock(PrevF(g[0]))); SetNextF(NextE(l), Clock(PrevF(PrevE(g[3])))); SetNextF(PrevE(l), NextF(NextE(g[2]))); /* Update the component @{edge->?} */ SetRingEdgeInfo(l, PEdge(g[0])); SetRingEdgeInfo(NextE(l), PEdge(PrevE(g[3]))); SetRingEdgeInfo(PrevE(l), PEdge(NextE(g[2]))); /* Update the origins */ SetOrg(l, OrgV(Clock(g[0]))); SetOrg(Clock(l), OrgV(g[0])); SetOrg(NextE(l), OrgV(Clock(l))); SetOrg(Clock(NextE(l)), OrgV(NextE(g[2]))); SetOrg(PrevE(l), OrgV(Clock(NextE(l)))); SetOrg(Clock(PrevE(l)), OrgV(l)); /* Subdivision of the Octahedron (in four tetrahedron) delimitate by the medial nodes */ ??? o1 = MakeTriangle(FALSE); ??? o2 = MakeTriangle(FALSE); ??? o3 = MakeTriangle(FALSE); ??? o4 = MakeTriangle(FALSE); { assert(i == PrevF(Clock(g[1]))); assert(i == Clock(NextF(g[1]))); assert(i == Clock(PrevE(NextF(g[2])))); assert(j == PrevF(NextE(g[0]))); assert(k == Clock(PrevF(PrevE(g[0])))); assert(k == Clock(PrevE(PrevF(g[3])))); assert(l == Clock(PrevF(g[0]))); /* triangle o1 */ SetNextF(o1, NextE(k)); SetNextF(PrevE(g[1]), o1); SetNextF(PrevE(o1), NextE(g[0])); SetNextF(j, PrevE(o1)); /* Update the component @{edge->?} */ SetRingEdgeInfo(o1, PEdge(NextE(k))); SetRingEdgeInfo(PrevE(o1), PEdge(j)); /* Update the origins */ SetOrg(o1, OrgV(PrevE(g[1]))); SetOrg(Clock(o1), OrgV(Clock(PrevE(g[1])))); SetOrg(PrevE(o1), OrgV(NextE(g[0]))); SetOrg(Clock(PrevE(o1)), OrgV(Clock(NextE(g[0])))); SetOrg(NextE(o1), OrgV(PrevE(k))); SetOrg(Clock(NextE(o1)), OrgV(j)); /* triangle o2 */ SetNextF(NextE(o2), NextE(g[3])); SetNextF(NextE(i), NextE(o2)); SetNextF(PrevE(o2), PrevE(l)); SetNextF(NextE(g[2]), PrevE(o2)); /* Update the component @{edge->?} */ SetRingEdgeInfo(NextE(o2), PEdge(NextE(g[3]))); SetRingEdgeInfo(PrevE(o2), PEdge(NextE(g[2]))); /* Update the origins */ SetOrg(o2, OrgV(j)); SetOrg(Clock(o2), OrgV(PrevE(k))); SetOrg(NextE(o2), OrgV(NextE(g[3]))); SetOrg(Clock(NextE(o2)), OrgV(Clock(NextE(g[3])))); SetOrg(PrevE(o2), OrgV(NextE(g[2]))); SetOrg(Clock(PrevE(o2)), OrgV(Clock(NextE(g[2])))); /* triangle o3 */ SetNextF(o3, l); SetNextF(Clock(g[0]), o3); SetNextF(NextE(o3), g[3]); SetNextF(Clock(PrevE(k)), NextE(o3)); /* Update the component @{edge->?} */ SetRingEdgeInfo(o3, PEdge(l)); SetRingEdgeInfo(NextE(o3), PEdge(g[3])); /* Update the origins */ SetOrg(o3, OrgV(Clock(g[0]))); SetOrg(Clock(o3), OrgV(g[0])); SetOrg(NextE(o3), OrgV(g[3])); SetOrg(Clock(NextE(o3)), OrgV(Clock(g[3]))); SetOrg(PrevE(o3), OrgV(PrevE(k))); SetOrg(Clock(PrevE(o3)), OrgV(j)); /* triangle o4 */ SetNextF(g[1], NextE(o4)); SetNextF(NextE(o4), Clock(i)); SetNextF(PrevE(j), PrevE(o4)); SetNextF(PrevE(o4), Clock(PrevE(g[2]))); SetNextF(o4, o2); SetNextF(o2, Clock(PrevE(o3))); SetNextF(Clock(PrevE(o3)), Clock(NextE(o1))); /* Update the component @{edge->?} */ SetRingEdgeInfo(NextE(o4), PEdge(Clock(i))); SetRingEdgeInfo(PrevE(o4), PEdge(PrevE(j))); SetRingEdgeInfo(o2, PEdge(o2)); /* Update the origins */ SetOrg(NextE(o4), OrgV(g[1])); SetOrg(Clock(NextE(o4)), OrgV(Clock(g[1]))); SetOrg(PrevE(o4), OrgV(Clock(PrevE(g[2])))); SetOrg(Clock(PrevE(o4)), OrgV(PrevE(g[2]))); SetOrg(o4, OrgV(o2)); SetOrg(Clock(o4), OrgV(Clock(o2))); /* making eigth tetrahedral cells */ SetPnegOfNearbyWalls(j); SetPnegOfNearbyWalls(Clock(PrevF(PrevE(NextF(k))))); SetPnegOfNearbyWalls(Clock(PrevF(NextE(i)))); SetPnegOfNearbyWalls(Clock(PrevF(NextE(NextF(l))))); SetPnegOfNearbyWalls(PrevE(NextF(o1))); SetPnegOfNearbyWalls(o2); SetPnegOfNearbyWalls(NextF(o3)); SetPnegOfNearbyWalls(o4); if (o->assert){ /* Some strong assertions */ assert(Org(Srot(j)) == Pneg(j)); assert(Org(Srot(Clock(PrevF(PrevE(NextF(k)))))) == Pneg(Clock(PrevF(PrevE(NextF(k)))))); assert(Org(Srot(Clock(PrevF(NextE(i))))) == Pneg(Clock(PrevF(NextE(i))))); assert(Org(Srot(Clock(PrevF(NextE(NextF(l)))))) == Pneg(Clock(PrevF(NextE(NextF(l)))))); assert(Org(Srot(NextF(o3))) == Pneg(NextF(o3))); assert(Org(Srot(PrevE(NextF(o1)))) == Pneg(PrevE(NextF(o1)))); assert(Org(Srot(o4)) == Pneg(o4)); assert(Org(Srot(o2)) == Pneg(o2)); Place_t v = Srot(j); Place_t v1 = Clock(PrevE(Srot(j))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(NextF(o3)); Place_t v1 = Clock(PrevE(Srot(NextF(o3)))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(o2); Place_t v1 = Clock(PrevE(Srot(o2))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(o4); Place_t v1 = Clock(PrevE(Srot(o4))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(PrevE(NextF(o1))); Place_t v1 = Clock(PrevE(Srot(PrevE(NextF(o1))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(PrevE(NextF(k))))); Place_t v1 = Clock(PrevE(Srot(Clock(PrevF(PrevE(NextF(k))))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(NextE(i)))); Place_t v1 = Clock(PrevE(Srot(Clock(PrevF(NextE(i)))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(NextE(NextF(l))))); Place_t v1 = Clock(PrevE(Srot(Clock(PrevF(NextE(NextF(l))))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } } /* Now, refine the subdivision of the octahedron in more four tetrahedra, through the subdivision of the diagonal @{edge->?} of the octahedron. */ Subdivide@{Edge->?}(o2,in,o->net); } } } RefineCell; bool_t CreateNode(Place_t @p) Place_t t = a; VAR { ??? fe = NARROW(PWedge(a)-> Wedge_t); { ){ if (! fe.mark) { fe.mark = TRUE; do { ??? fe = NARROW(PWedge(t), Wedge_t); { ){ fe.mark = TRUE; } t = NextF(t) } while (t != a); return TRUE; } return FALSE; } } CreateNode; void SetAllVh(Place_t @p, Node_t v) /* Set all adjacents @places to "a" with the same medial node "v" */ void SetVh(b: Place_t) /* Set the @place "b" with the medial node "v". */ { ??? fe = NARROW(PWedge(b)-> Wedge_t); { ){ fe.vh = v; } } SetVh; Place_t t = a; VAR { do { SetVh(t); t = NextF(t); } while (t != a); } SetAllVh; void SetPnegOfNearbyWalls(Place_t @p) /* set the (12) places belonging to same 3-cell */ Place_t t = a; VAR { Cell_t p = MakeCell(); { SetPnegOfWall(t,p); do { SetPnegOfWall(Clock(PrevF(t)),p); t = PrevE(t); } while (t != a); } } SetPnegOfNearbyWalls; uint Vhnum(Place_t @p) /* given the @place "a", this procedure return the number of its medial node "vh". */ { ??? fe = NARROW(PWedge(a)-> Wedge_t); { ){ return fe.vh->num; } } Vhnum; { /* Copy the original nodes, save icorrespondence in "vnew" array: */ for (iu = 0; iu < top->node.ne; iu++) { ??? u = top->node[iu]; Node_t v = MakeNode(); { v->num = u->num; v->exists = u->exists; v.fixed = u.fixed) || (o->fixOri; v.color = u.color; v.radius = u.radius; v.label = u.label; vnew[iu] = v } } /* Create two new wedges for each original wedge "fe". The new wedge corresponding to the origin half of "fe", with same spin and orientation, will be | Half(a) == Spin^s(half[2*PWedge(a)->num + o]) where s == SpinBit(a), o == OrientationBit(a) */ REF Node_vec_t ve = Node_vec_new(top->NE); uint i = 0; { for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? ho = half[2*ie + oa]; ??? hd = half[2*ie + 1 - oa]; ??? fe = NARROW(PWedge(a)-> Wedge_t); { double fn = fe.wall->num; double en = fe.edge->num ){ if (( CreateNode(a))) { ve[i] = MakeNode(); ve[i]->num = top->node.ne + NNV; NNV++; ve[i]->exists = top->edge[en]->exists; ve[i].fixed = FALSE; ve[i].color = top->edge[en].color; ve[i].transp = top->edge[en].transp; ve[i].radius = top->edge[en].radius; ve[i].label = "VE"; SetAllVh(a, ve[i]); i++; } ho = MakeWedge(); ??? hoe = NARROW(PWedge(ho)-> Wedge_t); { ){ hoe.edge->exists = top->edge[en]->exists; hoe.edge.color = top->edge[en].color; hoe.edge.transp = top->edge[en].transp; hoe.edge.radius = top->edge[en].radius; /* set the "root" @{edge->?} */ hoe.edge->root = top->edge[en]->root; hoe.wall->exists = top->wall[fn]->exists; hoe.wall.color = top->wall[fn].color; hoe.wall.transp = top->wall[fn].transp; } if (sa == 1){ ho = Spin(ho); } hd = MakeWedge(); ??? hde = NARROW(PWedge(hd)-> Wedge_t); { ){ hde.edge->exists = top->edge[en]->exists; hde.edge.color = top->edge[en].color; hde.edge.transp = top->edge[en].transp; hde.edge.radius = top->edge[en].radius; /* set the "root" @{edge->?} */ hde.edge->root = top->edge[en]->root; hde.wall->exists = top->wall[fn]->exists; hde.wall.color = top->wall[fn].color; hde.wall.transp = top->wall[fn].transp; } if (sa == 1){ hd = Spin(hd); } SpliceEdges(ho, Clock(hd)); ??? m = Vhnum(a); { SetOrg(Clock(ho),ve[m-top->node.ne]); SetOrg(Clock(hd),ve[m-top->node.ne]); } SetOrg(ho, vnew[OrgV(a)->num]); SetOrg(hd, vnew[OrgV(Clock(a))->num]); } } } /* Connect the half-wedges as in the original triangulation */ for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((c!=a) && (NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } Place_t a = Clock(top->wedge[ie]); Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } } for (j = 0; j < top->wall.ne; j++) { Place_t *d,e,f,g; { ??? fa = top->wall[j]; ??? fr = fa->root; ??? a = fa.pa; Place_t b = NextE(a); Place_t c = PrevE(a); ??? ha = Half(a); with (hac == Half(Clock(a)), double hb = Half(b), hbc == Half(Clock(b)); double hc = Half(c), hcc == Half(Clock(c)) ){ if ((((fa.node^).ne)!=3)){ BadElement(); } d = MakeWedge(); PEdge(d)->exists = Thin@{Edge->?}Exists; e = MakeWedge(); PEdge(e)->exists = Thin@{Edge->?}Exists; f = MakeWedge(); PEdge(f)->exists = Thin@{Edge->?}Exists; if ((fa->exists) && (o->net)) { with ( double co = (frgb_t){1.00,1.00,0.50}, /* color and radius for the thin */ double ra = 0.0025, /* @{edge->?} on the net */ double de = PEdge(d); double ee = PEdge(e); double fe = PEdge(f) ){ de->exists = TRUE; ee->exists = TRUE; fe->exists = TRUE; de.color = co; de.radius = ra; ee.color = co; ee.radius = ra; fe.color = co; fe.radius = ra; } } /* Make the first @{link->?} wedge */ SetNextE(hc, d); SetNextE(d, Clock(hbc)); SetNextE(Clock(hc), hbc); /* Update the origins */ SetOrg(d, OrgV(Clock(hc))); SetOrg(Clock(d), OrgV(Clock(hbc))); /* Update the component wall */ SetWallInfo(hc, PWall(d)); SetWallInfo(hbc, PWall(d)); PWall(d)->exists = top->wall[j]->exists; PWall(d).color = top->wall[j].color; PWall(d).transp = top->wall[j].transp; /* Make the second @{link->?} wedge */ SetNextE(ha, e); SetNextE(e, Clock(hcc)); SetNextE(Clock(ha), hcc); /* Update the origins */ SetOrg(e, OrgV(Clock(ha))); SetOrg(Clock(e), OrgV(Clock(hcc))); /* Update the component wall */ SetWallInfo(ha, PWall(e)); SetWallInfo(hcc, PWall(e)); PWall(e)->exists = top->wall[j]->exists; PWall(e).color = top->wall[j].color; PWall(e).transp = top->wall[j].transp; /* Make the third @{link->?} wedge */ SetNextE(hac, f); SetNextE(f, Clock(hb)); SetNextE(Clock(hac), hb); /* Update the origins */ SetOrg(f, OrgV(Clock(hac))); SetOrg(Clock(f), OrgV(Clock(hb))); /* Update the component wall */ SetWallInfo(hac, PWall(f)); SetWallInfo(hb, PWall(f)); PWall(f)->exists = top->wall[j]->exists; PWall(f).color = top->wall[j].color; PWall(f).transp = top->wall[j].transp; /* Create Triangular wall to insert */ if (top->wall[j]->exists ){ g = MakeTriangle(TRUE); } else { g = MakeTriangle(FALSE); } /* making the connections */ SetNextF(NextE(hc), Clock(g)); SetNextF(NextE(hbc), g); SetNextF(NextE(g), NextE(hcc)); SetNextF(Clock(NextE(g)), Clock(NextE(hcc))); SetNextF(Clock(NextE(hb)), PrevE(g)); SetNextF(Clock(NextE(hac)),Clock(PrevE(g))); /* Update the edge component */ SetRingEdgeInfo(g ,PEdge(d)); SetRingEdgeInfo(NextE(g) ,PEdge(e)); SetRingEdgeInfo(PrevE(g) ,PEdge(f)); /* Update the origins */ SetOrg(g, OrgV(Clock(d))); SetOrg(Clock(g), OrgV(d)); SetOrg(NextE(g), OrgV(Clock(e))); SetOrg(Clock(NextE(g)), OrgV(e)); SetOrg(PrevE(g), OrgV(f)); SetOrg(Clock(PrevE(g)), OrgV(Clock(f))); PWall(g).color = top->wall[j].color; PWall(g).transp = top->wall[j].transp; /* set the "root" wall */ PWall(d)->root = fr; PWall(e)->root = fr; PWall(f)->root = fr; PWall(g)->root = fr; /* end of the setting */ } } } for (i = 0; i < top->wall.nelE; i++) { ??? a = top->wedge[i]; ??? ha = Half(a); ??? hac = Half(Clock(a)); { SetRingEdgeInfo(ha, PEdge(ha)); SetRingEdgeInfo(hac, PEdge(hac)); } }; for (i = 0; i < top->cell.ne; i++) { ??? v = Srot(top.cell[i]); Place_t a = Tors(v); Place_t af = PrevF(a); Place_t ae = PrevE(a); Place_t aee = NextE(a); { assert(Pneg(a)->num == i); assert(Org(v)->num == i); if ((Ppos(af)!=NULL)){ assert(Pneg(a) == Ppos (af)); } if ((NUMBER(Pneg(a).node^)!=4)){ BadElement(); } gi[i,0] = Clock(NextE(PrevF(NextE(Half(a))))); gi[i,1] = Clock(NextE(NextF(NextE(Half(af))))); gi[i,2] = Clock(NextE(NextF(NextE(Half(PrevF(ae)))))); gi[i,3] = NextF(NextE(Half(PrevF(aee)))); } } for (i = 0; i < top->cell.ne; i++) { RefineCell(RowT{gi[i,0],gi[i,1],gi[i,2],gi[i,3]},i); } if (top->bdr == 0) { ntop = MakeElemTable(Half(top->wedge[1]),0); } else { ntop = MakeElemTable(Half(top->wedge[1]),1); } ??? nc = NEW(REF Coords_t; with (ntop.node.ne)^, double com = "Refined from: " & o->inFileTp & ".tp\n" & "Created by RefineTriang: " & o->outFile & ".tp" ){ assert(ntop.node.ne == top->node.ne + top->NE + top->cell.ne); assert(ntop.edge.ne == 2*top->NE + 3*top->wall.ne + 6*top->cell.ne); assert(ntop.wall.ne == 4*top->wall.ne + 16*top->cell.ne); assert(ntop.cell.ne == 12*top->cell.ne); if (top->bdr == 0){ assert(ntop.wedge.ne == 72*top->cell.ne); } for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Half(a))->num; Node_t nv = OrgV(Half(Clock(a)))->num; Node_t nx = OrgV(Clock(Half(a)))->num; Node_t ny = OrgV(Clock(Half(Clock(a))))->num; { assert(nx == ny); nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); } } if (o->net) { /* we compute the number of existing walls in the previus topology. */ VAR nefp: uint = 0; /* existing walls in the previus topology*/ neep: uint = 0; /* existing @{edge->?}s in the previus topology*/ neea: uint = 0; /* existing @{edge->?}s in the actual topology*/ { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists){ nefp++;} } } for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { if (e->exists){ neep++; } } } for (i = 0; i < ntop.edge.ne; i++) { ??? e = ntop.edge[i]; { if (e->exists){ neea++;} } } assert(neea == 3 * nefp + 2 * neep); } } for (i = 0; i < top->cell.ne; i++) { Node_t ou = OrgV(gi[i; with (1])->num, double ov = OrgV(PrevE(gi[i,2]))->num ){ nc[x[i]->num] = r4_Scale(0.5, r4_Add(nc[ou], nc[ov])); } } WriteTopology (o->outFile, ntop, com); WriteTable (o->outFile, ntop, com); WriteState (o->outFile, ntop, nc, com); WriteMaterials(o->outFile, ntop, com, FALSE); /* Now, unmark the attribute "mark" of Wedge_t */ for (i = 0; i < top->wall.nelE; i++) { ??? fe = NARROW(PWedge(top->wedge[i]), Wedge_t); { ){ if (fe.mark){ fe.mark = FALSE; } } } } } return 0; } PROCEDURE BadElement() { fprintf(stderr,"This topology isn't a triangulation\n"); Process.Exit¦(1); } /* END BadElement */ PROCEDURE Subdivide@{Edge->?}(an : Place_t; i: INTEGER; bool_t net) == VAR a,bn,m1,m2,m3,t0,t1,Place_vec_t t2; wn, p: REF ARRAY OF @{Node->?}; CONST double n = 4; { a = NEW(REF Place_vec_t,n); bn = NEW(REF Place_vec_t,n); m1 = NEW(REF Place_vec_t,n); m2 = NEW(REF Place_vec_t,n); m3 = NEW(REF Place_vec_t,n); t0 = NEW(REF Place_vec_t,n); t1 = NEW(REF Place_vec_t,n); t2 = NEW(REF Place_vec_t,n); /* save the @places */ a = NEW(REF Place_vec_t,n); a[0] = an; for (i = 1; i < n; i++) { a[i] = NextF(a[i-1]); } /* save the nodes */ wn = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { wn[i] = Org(PrevE(a[i])); } /* save the cells */ p = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { p[i] = Pneg(a[i]); } /* save other @places */ bn = NEW(REF Place_vec_t,n); for (i = 0; i < n; i++) { bn[i] = Clock(PrevE(NextF(PrevE(a[i])))); } /* insert wedges and edges */ for (i = 0; i < n; i++) { m1[i] = MakeWedge(); m2[i] = MakeWedge(); m3[i] = MakeWedge(); t0[i] = MakeTriangle(FALSE); t1[i] = NextE(t0[i]); t2[i] = NextE(t1[i]); /* If net==TRUE the simulates the net with cylinders ans spheres, */ if ((net) && (PEdge(bn[i])->exists)) { PEdge(t0[i])->exists = TRUE; PEdge(t0[i]).radius = 0.0025; PEdge(t0[i]).color = (frgb_t){1.0,1.0,0.5}; } ??? f = PWedge(t0[i]).wall; ??? e1 = PEdge(t1[i]); ??? e2 = PEdge(t2[i]); { f->exists = FALSE; e1->exists = FALSE; e2->exists = FALSE; } } /* Now subdivide @{edge->?} and extend the subdivision on the star of the edge */ x[i] = MakeNode(); ??? v = NARROW(x[i], Node); { ){ v->exists = FALSE; v.label = "VE"; } for (j = 0; j < n; j++) { ??? ee = PEdge(a[j]); ??? ff = PEdge(m2[j]); Place_t b = NextE(a[j]); Edge_t be = PEdge(b); Place_t c = NextE(b); Edge_t ce = PEdge(c); ??? u = Org(a[j]); ??? v = Org(b); ??? w = Org(c); with ( /* save the attributes of the edge-wall component of the @place a[j] */ f = PWedge(a[j]).wall, g = PWedge(m3[j]).wall, double ge = g->exists; h = PEdge(m3[j]) ){ ee->exists = FALSE; ff->exists = FALSE; SetNextE(a[j],m1[j]); SetNextE(m1[j],c); SetNextE(m2[j],m3[j]); SetNextE(m3[j],Clock(b)); SetOrg(a[j], u); SetOrg(Clock(a[j]), x[i]); SetOrg(m2[j],v); SetOrg(Clock(m2[j]), x[i]); SetOrg(m3[j], x[i]); SetOrg(Clock(m3[j]), w); SetOrg(m1[j], x[i]); SetOrg(Clock(m1[j]), w); SetNextF(m1[j],m3[j]); /* set the attributes for the wall component */ ge = FALSE; SetRingWallInfo(a[j],f); SetRingWallInfo(m3[j],g); SetRingEdgeInfo(m3[j],h); SetRingEdgeInfo(b,be); SetRingEdgeInfo(c,ce); SetRingEdgeInfo(a[j],ee); SetRingEdgeInfo(m2[j],ff); SetRingWallInfo(bn[j],PWedge(bn[j]).wall); SetRingWallInfo(PrevF(bn[j]),PWedge(PrevF(bn[j])).wall); } } for (j = 0; j < n; j++) { SetNextF(Clock(m2[j]),Clock(m2[(j+1) % n])); } ??? ff = PEdge(m2[0]); { SetRingEdgeInfo(m2[0],ff); } for (j = 0; j < n; j++) { Place_t cn = NextF(bn[j]); ??? e0 = PEdge(t0[j]); ??? e1 = PEdge(t1[j]); ??? e2 = PEdge(t2[j]); { SetOrgAll(t0[j],wn[j]); SetOrgAll(t1[j],wn[(j+1) % n]); SetOrgAll(t2[j],x[i]); SetNextF(bn[j], t0[j]); SetNextF(t0[j],cn); SetNextF(m1[j],t2[j]); SetNextF(t2[j],m3[j]); SetNextF(Clock(m1[(j+1) % n]), t1[j]); SetNextF(t1[j],Clock(m3[(j+1) % n])); SetRingEdgeInfo(t0[j],e0); SetRingEdgeInfo(t1[j],e1); SetRingEdgeInfo(t2[j],e2); SetRingEdgeInfo(NextE(t0[j]),PEdge(NextE(t0[j]))); SetRingEdgeInfo(NextE(t1[j]),PEdge(NextE(t1[j]))); SetRingEdgeInfo(NextE(t2[j]),PEdge(NextE(t2[j]))); } } /* insert cells */ for (j = 0; j < n; j++) { ??? q = Triangulation.MakeCell(); { Triangulation.SetPnegOfNearbyWalls(a[j],p[j]); Triangulation.SetPnegOfNearbyWalls(m2[j],q); } } } /* END Subdivide@{Edge->?} */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->fixOri = argparser_keyword_present(pp, "-fixOri"); o->net = argparser_keyword_present(pp, "-net"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: RefineTriang \\\n"); fprintf(stderr, " -inFileTp \\\n"); fprintf(stderr, " -inFileSt \\\n"); fprintf(stderr, " -outFile \\\n"); fprintf(stderr, " [ -fixOri ] [-assert] [-net]\n"); END¦ } } return o; } GetOptions; Place_t MakeTriangle(bool_t exists) /* Make one triangular wall and set of the three places with the same wall component. If exists is TRUE then the triangular wall exists, FALSE otherwise. */ { Place_t a = MakeWedge(); Place_t b = MakeWedge(); Place_t c = MakeWedge(); Wall_t f = PWall(a); Node_t u = MakeNode(); Node_t v = MakeNode(); Node_t w = MakeNode(); { if (exists){ f->exists = TRUE }else{ f->exists = FALSE; } PEdge(a)->exists = Thin@{Edge->?}Exists; SetOrg(a, u); SetOrg(Clock(a),v); PEdge(b)->exists = Thin@{Edge->?}Exists; SetNextE(a,b); SetWallInfo (b,f); SetOrg (b,v); SetOrg(Clock(b),w); PEdge(c)->exists = Thin@{Edge->?}Exists; SetNextE(b,c); SetWallInfo (c,f); SetOrg (c, w); SetOrg(Clock(c), OrgV(a)); return a; } } /* END MakeTriangle */ { DoIt() } RefineTriang. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/MatrixRotation.c #define PROG_NAME "MatrixRotation" #define PROG_DESC "???" #define PROG_VERS "1.0" #define MatrixRotation_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " #include #include #include #include #include TYPE Row == ARRAY[0..3] OF double; VAR U,V : r3_t; CONST double Identity = LR4x4.T{ Row{1.0, 0.0, 0.0, 0.0}; Row{0.0, 1.0, 0.0, 0.0}, Row{0.0, 0.0, 1.0, 0.0}, Row{0.0, 0.0, 0.0, 1.0} } double IdentityN = LR4x4.T{ Row{-1.0, 0.0, 0.0, 0.0}; Row{ 0.0,-1.0, 0.0, 0.0}, Row{ 0.0, 0.0,-1.0, 0.0}, Row{ 0.0, 0.0, 0.0, 1.0} } void WriteLong(FILE *wr, double x) { fprintf(wr, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 4), 8)); } /* END WriteLong */ double ReadLong() { return Scan.LongReal(Rd.GetLine(Stdio.stdin)); } /* END ReadLong */ LR4x4.T ComputeMatrixRotation(*u,v: r3_t) { with ( x == (r3_t){1.0,0.0,0.0}, double uu = LR3.Dir(r3_sub(v,u)) ){ if ((LR3.Dist(uu,x) <= 0.00001)){ return Identity; } else { ??? vv = LR3.Dir(LR3Extras.Cross(x; with (uu)), double ww = LR3.Dir(LR3Extras.Cross(uu,vv)) DO return LR4x4.T{ (r4_t){ uu[0], uu[1], uu[2], 0.0}, (r4_t){ vv[0], vv[1], vv[2], 0.0}, (r4_t){ ww[0], ww[1], ww[2], 0.0}, (r4_t){ 0.0, 0.0, 0.0, 1.0} } } } } } /* END ComputeMatrixRotation */ /* UNUSED */ LR4x4.T ComputeInverse(*m: LR4x4.T) { return LR4x4.Inv(m); } /* END ComputeInverse */ { fprintf(stderr,"Input the U point (one component by line)\n\n"); fprintf(stderr,"U\n"); for (i = 0; i < 3; i++) { U[i] = ReadLong(); } fprintf(stderr, "Input the V point\n\n"); fprintf(stderr, "V\n"); for (i = 0; i < 3; i++) { V[i] = ReadLong(); } ??? matrix = ComputeMatrixRotation(U; with (V) ){ fprintf(stderr, "Matrix\n"); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { WriteLong(stderr, matrix[i,j]); } fprintf(stderr,"\n"); } fprintf(stderr,"\n"); } } MatrixRotation. /* Input the U point (one component by line) U 1 1 0 Input the V point V 2 2 0 Matrix 0.7071 -0.7071 -0.0000 0.0000 0.7071 0.7071 0.0000 0.0000 0.0000 -0.0000 1.0000 0.0000 0.0000 0.0000 0.0000 1.0000 Input the U point (one component by line) U 0 1 1 Input the V point V 0 2 2 Matrix 1.0000 -0.0000 -0.0000 0.0000 0.0000 0.7071 0.7071 0.0000 0.0000 -0.7071 0.7071 0.0000 0.0000 0.0000 0.0000 1.0000 Input the U point (one component by line) U 1 0 1 Input the V point V 2 0 2 Matrix 0.7071 -0.0000 -0.7071 0.0000 0.7071 0.0000 0.7071 0.0000 0.0000 -1.0000 0.0000 0.0000 0.0000 0.0000 0.0000 1.0000 */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/NewExplode.c #define PROG_NAME "NewExplode" #define PROG_DESC "???" #define PROG_VERS "1.0" #define NewExplode_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program recieves as input a triangulated tetrahedron of order $k$ (produced by the BuildRefinement program) and drawing it in explode way. */ #define NewExplode_C_author \ "Created on 26-12-2000 by lozada\n" // #INCLUDE #include #include // #INCLUDE #include #include // #INCLUDE // #INCLUDE TYPE typedef struct Options_t { char *inFileTp; /* Input file name (minus ".tp" extension) */ inFileSt3: char *; /* Input file name (minus ".st3" extension) */ char *outFile; /* Output file name prefix */ REAL opacity; /* opacity factor */ REAL radius; /* radius drawing */ double factor; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) <* FATAL OSError.E); { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? inc = FileWr.Open(o->outFile & "-Ex.inc"); ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Tridimensional.ReadState3D(o->inFileSt3); ??? c = rc^; { for (i = 0; i < top->cell.ne; i++) { ??? r = Srot(top.cell[i]); Place_t a = Tors(r); ??? pi = TetraNegNodes(a); with ( /* nodes */ c0 == c[pi[0]->num], c1 == c[pi[1]->num], c2 == c[pi[2]->num], c3 == c[pi[3]->num], double inv = o->factor/10.0; double bar = r3_scale(1.0/inv, r3_add(r3_add(r3_add(c0,c1),c2),c3)); /* adjusting to the barycenter tetrahedron */ double ue3 = r3_add(c0,bar); double ve3 = r3_add(c1,bar); double we3 = r3_add(c2,bar); double xe3 = r3_add(c3,bar); ra == o->radius, cf == (frgb_t){1.000, 1.000, 1.000}, ce == (frgb_t){0.0,0.0,0.0}, tr == o->opacity DO /* Drawing cylinders */ WritePOVCylinder(inc,ue3,ve3,ra,ce,0.0,TRUE); WritePOVCylinder(inc,ve3,we3,ra,ce,0.0,TRUE); WritePOVCylinder(inc,ue3,we3,ra,ce,0.0,TRUE); WritePOVCylinder(inc,ue3,xe3,ra,ce,0.0,TRUE); WritePOVCylinder(inc,ve3,xe3,ra,ce,0.0,TRUE); WritePOVCylinder(inc,we3,xe3,ra,ce,0.0,TRUE); /* Drawing triangles */ WritePOVTriangle(inc,ue3,ve3,we3,cf,tr,TRUE); WritePOVTriangle(inc,ue3,ve3,xe3,cf,tr,TRUE); WritePOVTriangle(inc,ve3,we3,xe3,cf,tr,TRUE); WritePOVTriangle(inc,ue3,we3,xe3,cf,tr,TRUE); /* Drawing spheres */ WritePOVSphere(inc,ue3,ra,ce,0.0,TRUE); WritePOVSphere(inc,ve3,ra,ce,0.0,TRUE); WritePOVSphere(inc,we3,ra,ce,0.0,TRUE); WritePOVSphere(inc,xe3,ra,ce,0.0,TRUE); } } return 0; } Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt3"); o->inFileSt3 = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-opacity"))) { o->opacity = pp.getNextReal(0.0, 1.0); } else { o->opacity = 0.65; }; if ((argparser_keyword_present(pp, "-radius"))) { o->radius = pp.getNextReal(0.0, 0.1); } else { o->radius = 0.005; }; if ((argparser_keyword_present(pp, "-factor"))) { o->factor = pp.getNextLongReal(0.0, 100.0); }; argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: NewExplode \\\n" \ " -inFileTp \\\n" \ " -inFileSt3 \\\n" \ " -outFile \\\n" \ " [-opacity ] [-radius \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } NewExplode. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/OptShape.c #define PROG_NAME "OptShape" #define PROG_DESC "???" #define PROG_VERS "1.0" #define OptShape_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Adjusts the node coordinates of a triangulation so as to minimize some energy function. Created 1994 by Rober Marcone Rosi and J.Stolfi. */ // #INCLUDE #include #include #include #include #include #include #include // // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // #INCLUDE // Coords3D_t; // #INCLUDE // Coords_t, Topology, OrgV; // #INCLUDE // Gradient; #include // #INCLUDE // Clock; // #INCLUDE CONST double Epsilon = 0.0000000001; /* aditional constants for 4D */ double From4 = (r4_t){0.0,0.0,0.0,-3.0}; /* 4D viewing parameter as */ double To4 = (r4_t){0.0,0.0,0.0,0.0}; /* expected by the "Wire4" */ double Up4 = (r4_t){0.0,1.0,0.0,0.0}; /* Interactive 4D Wireframe */ double Over4 = (r4_t){0.0,0.0,1.0,0.0}; /* Display Program. */ VAR Wa,Wb,Wc,Wd: r4_t; /* the 4 basis vectors for the 4D viewing matrix */ Data4Radius = 0.0; /* radius of the 4D data */ improvements,writestep: uint = 1; writetime: double = 0.0; TYPE typedef struct Options_t { char *inFileTp; /* Initial guess file name (minus ".tp") */ char *inFileSt; /* Initial guess file name (minus ".st") */ char *outFile; /* Output file name prefix */ eFunction: MixedEnergy.T; /* Energy Mixed function to minimize */ minimizer: Minimizer.T; /* Algorithm Minimization method to use */ uint nPasses; /* Number Of minimization passes */ uint maxEvals; /* Max energy evaluations per pass */ uint nodesPerPass; /* Max nodes top optimize in each pass */ bool_t only3D; /* TRUE==constrains the model to R^{3} */ uint writeEvery; /* When to write ".std" file */ uint printEvery; /* Print energies every this many steps. */ bool_t showAll; /* TRUE to display after each pass. */ bool_t showBest; /* TRUE to display only the best conf so far.*/ bool_t wait; /* TRUE to wait for mouse click af each pass */ double scale; /* set the scale for the visualization proc. */ bool_t complete; /* for compute overall files */ } double EvalRec = RECORD /* A Record of energy data: */ c: REF Coords_t; /* Pointer to Node coordinates */ double e; /* Total energy */ termValue: REF double_vec_t; /* Pointer to Unweighted energy terms */ eDc: REF Gradient /* Pointer to Gradient of total energy "e" r.to "c"*/ } double double = double; double_vec_t == double_vec_t; double bool_t = bool_t; bool_vec_t == ARRAY OF bool_t; double uint = uint; CARDS == uint_vec_t; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) <* FATAL OSError.E, Thread.Alerted, Wr.Failure); { /* compute the 4D viewing matrix */ CalcV4Matrix(); Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? rc = Triangulation.ReadState(o->inFileSt); { fprintf(stderr, "Optimizing from: " & o->inFileTp & ".tp\n"); if (o->complete) { ??? gnuWr = FileWr.Open(o->outFile & ".gnu"); { WriteGNUPlotCommands(gnuWr, o->outFile, o->eFunction.term^); fclose(gnuWr) } } if (o->only3D) { for(v = 0; v < rc.ne; v++) { rc[v,3] = 0.0; } } ??? plotWr = FileWr.Open(o->outFile & ".plot"); { if (o->complete) { WritePlotComments(plotWr, o->eFunction, o->minimizer); WritePlotHeader(plotWr, o->eFunction.term^); } if ((o->printEvery < (uint.ne-1))) { WritePlotHeader(stderr, o->eFunction.term^); } Minimize( tc, rc, o->minimizer, o->eFunction, nPasses = o->nPasses, maxEvals = o->maxEvals, nodesPerPass = o->nodesPerPass, only3D = o->only3D, writeEvery = o->writeEvery, printEvery = o->printEvery, inFile = o->inFileTp, outFile = o->outFile, plotWr = plotWr, showAll = o->showAll, showBest = o->showBest, wait = o->wait, scale = o->scale, complete = o->complete ); fclose(plotWr) } return 0; } PROCEDURE Minimize( *tc: Triangulation.TopCom_t; *rc: REF Coords_t; m: Minimizer.T; /* Minimization method */ e: MixedEnergy.T; /* Mixed Energy function */ uint nPasses; /* number of passes */ uint maxEvals; /* Evaluation budget per node minimization */ uint nodesPerPass; /* Min. this at most this many nodes per pass */ bool_t only3D; /* TRUE==constrains the model to R^{3} */ uint writeEvery; /* When to write ".tp" file */ uint printEvery; /* Print energies every thsi many steps. */ char *outFile; /* output file name prefix */ char *inFile; /* input file name prefix */ plotWr: Wr.T; /* Energy plots */ bool_t showAll; /* TRUE to display after each eval. */ bool_t showBest; /* TRUE to display only the best config so far. */ bool_t wait; /* TRUE to wait for user clicks at each pass */ double scale; /* set the scale for the visualization proc. */ bool_t complete; /* TRUE to wait for user clicks at each pass */ ) /* Minimization consists of "nPasses" passes, each starting at the best configuration found in the previous pass, and budgeted for "maxEvals" energy evaluations. At each pass, up to "nodesPerPass" nodes are selected (in a round-robin fashion) to be optimized, while the rest is held fixed. */ VAR totEvals: uint = 0; /* Count calls to "e.eval". */ cpuTime: double = 0.0; /* Accum minimization CPU time, seconds.*/ cpuWhen: double = 0.0; /* When minimization was (re)started. */ uint passCt; /* Counts optimization passes. */ window: ScreenPlot.T; /* The optimization movie. */ nextNode: uint = 0; /* Next node to optimize */ { ??? top = tc.top; int NV = top->node.ne; ??? NT = ((e.term^).ne); ??? rMin = NewEvalRec(NV; with ( NT)^, /* Best configuration found so far. Minimun Configuration */ double variable = VariableNodes(top)^, /* Oficially variable nodes */ double NB = CountTrue(variable), /* Number of variable nodes */ double NS = MIN(NB, nodesPerPass), /* Num of vert.to opt. per pass. */ double NC = 4*NS, /* Num of variables to optimize. */ double selected = bool_vec_new(NV)^, /* Nodes being minimized */ /* The following are work areas for "DoMinimizeStep": */ double rWork = NewEvalRec(NV, NT)^, /* Probe configuration */ double cIndex = NEW(REF CARDS, NC)^, /* Maps minimizer vars to coords */ double xm = NEW(REF Minimizer.Point, 4*NV)^,/* Argument vector for min. */ double fm = NEW(REF Minimizer.Value)^, /* Function value for minimizer */ double gm = NEW(REF Minimizer.Gradient, 4*NV)^, /* Gradient for minimizer */ /* Used by "ReportEval: */ double minComment = "energy function: " & e.name() & "\n" \ "minimizer: " & m.name() & "\n" \ "minimization passes == " & Fmt.Int(nPasses) & "\n" \ "nodes per pass == " & Fmt.Int(nodesPerPass) & "\n" \ "max evals per pass == " & Fmt.Int(totEvals) & "\n" \ "---------------------------------------" \ "---------------------------------------\n" \ "\nOptimized from: " & inFile & ".tp\n" & "\nCreated by OptShape: " & outFile & "\n" ){ /* Create the plot window: */ if ((showAll) || (showBest)) { ??? c3D = ProjectTo3D(top; with (rc^,scale) ){ window = MakeWindow(top,c3D^); } } /* Start the clock: */ cpuWhen = CPUTime.Now(); /* Tell the energy function what topology we are evaluationg: */ e.defTop(tc.top); /* Tell the minimizer how many variables are we going to minimize over; */ EVAL m.setSize(NC); /* Initialize the minimum configuration: */ rMin.c^ = rc^; passCt = 0; while (1) { /* Do a full evaluation once in a while, to get the total energy right. Ideally, a full evaluation should be necessary only once at the beginning, but doing it at every pass reduces the effect of rounding errors, and and provides a good check against programming errors. */ double eOld = rMin.e; VAR { for (v = 0; v < NV; v++){ selected[v] = TRUE; } e.defVar(variable); e.eval(rMin.c^, rMin.e, FALSE, rMin.eDc^); totEvals++; rMin.termValue^ = e.termValue^; /* Stop the clock: */ cpuTime = cpuTime + (CPUTime.Now() - cpuWhen); IF passCt!=0 AND rMin.e - eOld > 1.0d-6 * MAX(fabs(rMin.e), fabs(eOld)) )){ Debug.Line("pass == " & Fmt.Int(passCt DIV NV)); Debug.LongReal("energy discrepancy == ", LRN.T{rMin.e - eOld}); Debug.Line("") } ReportConfiguration(outFile, top,plotWr, window, showAll, showBest, wait, cpuTime, totEvals, passCt, nPasses, writeEvery, printEvery, selected, rMin, rMin, e, minComment,scale,complete ); if ((passCt == 0) || (passCt == nPasses)) { /* Write configuration as ".tp": */ with ( double name = outFile \ ARRAY bool_t OF char *{"-initial", "-final"}[passCt >= nPasses] ){ WriteConfiguration( name, top, e, rMin, cpuTime = cpuTime, totEvals = totEvals, passCt = passCt, comment = minComment ) } } /* Restart the clock: */ cpuWhen = CPUTime.Now(); } if (passCt >= nPasses){ EXIT; } /* Select the nodes to optimize: */ assert(NS <= NB); if (NS == NB){ assert(nextNode == 0); } for (v = 0; v < NV; v++){ selected[v] = FALSE; } uint k = 0; VAR { while (k < NS) { ??? v = nextNode; { if (variable[v]) { selected[v] = TRUE; cIndex[4*k+0] = 4*v+0; cIndex[4*k+1] = 4*v+1; cIndex[4*k+2] = 4*v+2; cIndex[4*k+3] = 4*v+3; k++ } nextNode = (v + 1) % NV } } assert(k==NS); } assert(CountTrue(selected) == NS); void ReportEval(*rWork, rMin: EvalRec) { /* Stop the clock: */ cpuTime = cpuTime + (CPUTime.Now() - cpuWhen); INC (totEvals); ReportConfiguration(outFile, top,plotWr, window, showAll, showBest, wait, cpuTime, totEvals, passCt, nPasses, writeEvery, printEvery, selected, rWork, rMin, e, minComment,scale,complete ); /* Restart the clock: */ cpuWhen = CPUTime.Now(); } ReportEval; { /* Start the clock: */ cpuWhen = CPUTime.Now(); e.defVar(selected); DoMinimizeStep( m, e, rMin, cIndex = SUBARRAY(cIndex, 0, NC), maxEvals = maxEvals, only3D = only3D, reportEval = ReportEval, rWork = rWork, xm = SUBARRAY(xm, 0, NC), fm = fm, gm = SUBARRAY(gm, 0, NC) ) } passCt++ } /*while (1){*/; /* Stop the clock: */ cpuTime = cpuTime + (CPUTime.Now() - cpuWhen); /* Return minimum: */ rc^ = rMin.c^ } } /* END Minimize */ PROCEDURE ReportConfiguration( char *outFile; /* output file name prefix */ *ElemTableRec_t *top; plotWr: Wr.T; /* Energy plot file */ window: ScreenPlot.T; /* Dynamic display window */ bool_t showAll; /* TRUE to show all on "window" */ bool_t showBest; /* T. to show only best config so far on screen*/ bool_t wait; /* TRUE to wait for user click */ double cpuTime; /* Accumulated minimization CPU time so far */ uint totEvals; /* Accumulated energy evaluations so far */ uint passCt; /* Passes completed so far */ <*UNUSED);nPasses: uint; /* Max passes to perform */ <*UNUSED);writeEvery:uint;/* When to write the ".st" file. */ uint printEvery; /* Print energies every this many steps. */ bool_vec_t *selected; /* Nodes that are or were selected for opt. */ EvalRec *rWork; /* Last evaluated configuration */ EvalRec *rMin; /* Best configuration found so far */ e: MixedEnergy.T; /* The energy function */ char *minComment; /* Comment for ".tp" and ".st" files */ double scale; /* set the scale for the visualization proc. */ bool_t complete; ) { if (complete) { PlotEnergy(plotWr, cpuTime, totEvals, passCt, rWork, e.weight^); } if (totEvals % printEvery == 0) { PlotEnergy(stderr, cpuTime, totEvals, passCt, rMin, e.weight^) } /* improvements for iterations */ if (improvements >= 10 * writestep){ writestep = 10 * writestep; } if (((improvements % writestep) == 0) && (complete)) { ??? name = outFile & "-" & Fmt.Int(improvements) & "-e"; { WriteConfiguration( name, top, e, rMin, cpuTime = cpuTime, totEvals = totEvals, passCt = passCt, comment = ARRAY bool_t OF char *{"", minComment}[passCt == 0] ); } } improvements++; IF(writetime-2.0 * FLOAT(ROUND(writetime) DIV 2,double) <= 0.005) AND complete)) { /* improvements for cpu time */ ??? name = outFile & "-" \ Fmt.Pad(Fmt.LongReal(cpuTime, Fmt.Style.Fix); with(prec=2),5,'0') & "-t" ){ WriteConfiguration( name, top, e, rMin, cpuTime = cpuTime, totEvals = totEvals, passCt = passCt, comment = ARRAY bool_t OF char *{"", minComment}[passCt == 0] ); } } writetime = cpuTime; if ((showAll) || ((showBest) && (rWork.e == rMin.e))) { ??? c3D = ProjectTo3D(top; with (rWork.c^,scale) /*, double name = outFile & "-" & Fmt.Int(improvements) */ ){ DisplayConfiguration(window, c3D^, selected, wait); /*WriteConfigurationToOpenGL(top, c3D^);*/ /* here display the 3D configuration with OpenGL routines */ /* testing if (improvements >= 10 * writestep){ writestep = 10 * writestep; } if (((improvements % writestep) == 0)) { WriteConfigurationToOpenGL(top, c3D^, name); } */ } } } /* END ReportConfiguration */ bool_vec_t *VariableNodes(ElemTableRec_t *top)== /* Basically, set "vVar.e[v->num]=TRUE" iff node "v" exists and aren't fixed. I can set this boolean vector. */ { ??? r = bool_vec_new(top->node.ne); { Triangulation.GetVariableNodes(top, r^); return r; } } /* END VariableNodes */ EvalRec *NewEvalRec(NV, NT: uint)== { ??? r = NEW(REF EvalRec); { r^ = EvalRec { c = NEW(REF Coords_t, NV), e = 0.0, double_vec_t termValue = double_vec_new(NT), eDc = NEW(REF Gradient, NV) }; return r; } } /* END NewEvalRec */ TYPE double ReportEvalProc = PROCEDURE (*rWork, rMin: EvalRec); PROCEDURE DoMinimizeStep( m: Minimizer.T; /* Minimization method */ e: MixedEnergy.T; /* Energy function */ EvalRec *rMin; /* In: initial guess, Out: minimum */ CARDS *cIndex; /* Maps minimizer args to node coords */ uint maxEvals; /* Evaluation budget */ bool_t only3D; /* TRUE==constrains the model to R^{3} */ ReportEvalProc reportEval; /* Called after every energy evaluation */ /* Work areas: */ EvalRec *rWork; /* Probe configuration */ VAR xm: Minimizer.Point; /* Argument vector for minimizer */ VAR fm: Minimizer.Value; /* Function value for minimizer */ VAR gm: Minimizer.Gradient; /* Gradient vector for minimizer */ ) /* Performs an energy minimization for the nodes defined by the "cIndex" vector. Assumes that "m.setSize", "e.setTop", "e.setVar" have already been called. */ { ??? NT = ((e.term^).ne); ??? NC = (cIndex.ne); ??? grad = m.needsGradient(); with ( /* TRUE to compute gradients */ double eOffset = NEW(REF double)^, /* "eval(variable)-eval(selected)" */ double termOffset = double_vec_new(NT)^, /* Unweigthed terms of "eOffset" */ double cMin = rMin.c^; double eMin = rMin.e; double eDcMin = rMin.eDc^; double termMin = rMin.termValue^; double cWork = rWork.c^; double eWork = rWork.e; double eDcWork = rWork.eDc^; double termWork = rWork.termValue^ ){ void Initialize( VAR x: Minimizer.Point; VAR f: Minimizer.Value; VAR g: Minimizer.Gradient ) { cWork = cMin; e.eval(cWork, eWork, grad, eDcWork); termWork = e.termValue^; /* Save offsets between full and partial evaluations: */ eOffset = eMin - eWork; eWork = eMin; for (t = 0; t < NT; t++) { termOffset[t] = termMin[t] - termWork[t]; } termWork = termMin; reportEval(rWork, rMin); /* Set function and gradient: */ f = eWork + eOffset; for (i = 0 TO (x.ne-1)) { ??? vk = cIndex[i], v == vk DIV 4, k == vk % 4; { x[i] = cWork[v][k]; if ((k == 3) && (only3D )){ g[i] = 0.0; assert(x[i] == 0.0); } else { g[i] = eDcWork[v][k]; } } } } Initialize; void Eval( *x: Minimizer.Point; VAR f: Minimizer.Value; VAR g: Minimizer.Gradient ) { /* Stuff the argument into the "cWork" vector: */ for (i = 0 TO (x.ne-1)) { ??? vk = cIndex[i], v == vk DIV 4, k == vk % 4; { cWork[v][k] = x[i]; } } /* Evaluate the partial energy for "cWork": */ e.eval(cWork, eWork, grad, eDcWork); termWork = e.termValue^; /* Correct to full energy: */ eWork = eWork + eOffset; for (t = 0; t < NT; t++) { termWork[t] = termWork[t] + termOffset[t] } /* See if we got something good: */ if (eWork < eMin) { eMin = eWork; cMin = cWork; eDcMin = eDcWork; termMin = termWork; } reportEval(rWork, rMin); /* Return energy and gradient to optimizer: */ f = eWork; if (grad) { for (i = 0 TO (g.ne-1)) { ??? vk = cIndex[i], v == vk DIV 4, k == vk % 4; { if ((k == 3) && (only3D)){ g[i] = 0.0 } else { g[i] = eDcWork[v][k]; } } } } } Eval; /* Now do a partial one to get us started: */ { Initialize(xm, fm, gm); m.minimize( eval = Eval, x = xm, f = fm, g = gm, dist = Math.pow(FLOAT(NC,double),1.0/3.0), /* dist==rough guess between the starting point and the optimun set */ tol = 0.05, /* upper bound tolerance for the size of the optimun set */ flat = 0.0, maxEvals = maxEvals ); /* Sanity check: */ if (fm != eMin) { Debug.LongReal("** bug: fm, eMin == ", LRN.T{fm, eMin}) } } } } /* END DoMinimizeStep */ uint CountTrue(*b: bool_vec_t) uint n = 0; { for (i = 0 TO (b.ne-1)){ if (b[i]){ n++; } } return n; } /* END CountTrue */ ScreenPlot.T MakeWindow(ElemTableRec_t *top, *c3: Coords3D_t; ) { /* Allocate window for "2*NV+1" points: "[0..NV-1]" are the mesh nodes, "[NV..2*NV-1]" are the marks, "[2*NV]" is the origin. */ int NV = top->node.ne; ??? NE = top->NE; ??? NP = 2*NV + 1; ??? w = NEW(ScreenPlot.T).init(NP); ??? org = NP-1; { w.pause(); w.setCoords(0, c3); /* @{Edge->?}s* */ for (i = 0; i < NE; i++) { ??? e = top->edge[i]; ??? a = e.pa; Node_t u = OrgV(a)->num; Node_t v = OrgV(Clock(a))->num; { w.segment(u, v, width = 0.0) } } /* Node marks: */ for (i = 0; i < NV; i++) { ??? p = NV+i; { w.setCoord(p, (r3_t){0.0, ..}); /* For the time being */ w.point(p, size = 5.0) } } /* Origin: */ w.setCoord(org, (r3_t){0.0, ..}); /* For the time being */ w.point(org, size = 7.0); w.resume(); EVAL w.waitKey(); return w; } } /* END MakeWindow */ PROCEDURE DisplayConfiguration( w: ScreenPlot.T; *c3: Coords3D_t; bool_vec_t *marked; bool_t wait; ) { int NV = (c3.ne); ??? org = 2*NV; { w.pause(); w.setCoords(0, c3); /* Marked nodes: */ uint p = NV; VAR { for (v = 0; v < NV; v++) { if (marked[v]) { w.setCoord(p, c3[v]); p++ } } while (p < org) { w.setCoord(p, (r3_t){0.0, ..}); p++ } } w.resume(); if (wait){ EVAL w.waitKey() }else{ w.waitDone(); } } } /* END DisplayConfiguration */ void WriteConfiguration(char *name, ElemTableRec_t *top, e: MixedEnergy.T; EvalRec *r; cpuTime: CPUTime.T; uint totEvals; uint passCt; char *comment; ) { WriteState(name,top, r.c^, cmt = comment & IterationComments(cpuTime, totEvals, passCt, r, e) & "\n"); } /* END WriteConfiguration */ PROCEDURE IterationComments( double cpuTime; uint *totEvals; uint *step; EvalRec *r; *e: MixedEnergy.T; ): char *== { ??? wr = NEW(TextWr.T).init(); { WritePlotHeader(wr, e.term^); PlotEnergy(wr, cpuTime, totEvals, step, r, e.weight^); return TextWr.ToText(wr); } } /* END IterationComments */ PROCEDURE PlotEnergy( FILE *wr, double *cpuTime; uint *totEvals; uint *step; EvalRec *r; *weight: ARRAY OF REAL; ) { PutText(wr, " "); PutText(wr, Fmt.Pad(Fmt.LongReal(cpuTime,Fmt.Style.Fix, prec = 2), 8)); PutText(wr, " "); PutText(wr, Fmt.Pad(Fmt.Int(totEvals), 8)); PutText(wr, " "); PutText(wr, Fmt.Pad(Fmt.LongReal(r.e, Fmt.Style.Fix, 5), 12)); PutText(wr, " "); PutText(wr, Fmt.Pad(Fmt.Int(step), 8)); for (i = 0 TO LAST(r.termValue^)) { PutText(wr, " "); ??? t = r.termValue[i] * ((double)weight[i]); { PutText(wr, Fmt.Pad(Fmt.LongReal(t, Fmt.Style.Fix, 5), 12)) } } PutText(wr, "\n"); fflush(wr); } /* END PlotEnergy */ void WritePlotComments(FILE *wr, e: MixedEnergy.T; m: Minimizer.T) { PutText(wr, "#"); PutText(wr, " energy function: " & e.name()); PutText(wr, "\n"); PutText(wr, "#"); PutText(wr, " minimizer: " & m.name()); PutText(wr, "\n"); fflush(wr); } /* END WritePlotComments */ void WritePlotHeader(FILE *wr, *term: ARRAY OF Energy.T) { PutText(wr, "#"); PutText(wr, Fmt.Pad("cpuTime", 8)); PutText(wr, " "); PutText(wr, Fmt.Pad("evals", 8)); PutText(wr, " "); PutText(wr, Fmt.Pad("energy", 12)); PutText(wr, " "); PutText(wr, Fmt.Pad("step", 8)); for (i = 0 TO (term.ne-1)) { PutText(wr, " "); PutText(wr, Fmt.Pad(EnergyTag(term[i].name()), 12)); } PutText(wr, "\n"); fflush(wr); } /* END WritePlotHeader */ void WriteGNUPlotCommands(FILE *wr, outFile: char *; *term: ARRAY OF Energy.T) { PutText(wr, "set terminal X11\n"); /*PutText(wr, "set output \"" & outFile & ".tex\"\n");*/ PutText(wr, "set xlabel \"Cpu-Time\"\n"); PutText(wr, "set ylabel \"Energy\"\n"); PutText(wr, "set title \"" & outFile & "\"\n"); PutText(wr, "plot \"" & outFile \ ".plot\" using 1:3 title \"TotalE\" with lines, \\\n"); for (i = 0 TO (term.ne-1)) { ??? col = i + 5; { PutText(wr, " \"" & outFile & ".plot\" using 1:" \ Fmt.Int(col) & " title \"" &EnergyTag(term[i].name()) \ "\" with linespoints"); if ((i < (term.ne-1))){ PutText(wr, ", \\"); } PutText(wr, "\n"); } } PutText(wr, "pause 30\n"); PutText(wr, "quit\n"); fflush(wr); } /* END WriteGNUPlotCommands */ PROCEDURE EnergyTag(char *name): char *== { ??? n = Text.FindChar(name; with ( '(') ){ if (n == -1) { return Text.Sub(name, 0, 8); } else { return Text.Sub(name, 0, MIN(n, 8)); } } } /* END EnergyTag */ PROCEDURE CalcV4Matrix() /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ { /* Calculate Wd, the 4th coordinate basis vector and line-of-sight. */ Wd = r4_Sub(To4,From4); if ((r4_Norm(Wd) < Epsilon)) { fprintf(stderr, "4D To Point and From Point are the same\n"); Process.Exit¦(1); } Wd = r4_Scale(1.0/r4_Norm(Wd), Wd); /* Calculate Wa, the X-axis basis vector. */ Wa = r4_cross(Up4,Over4,Wd); if ((r4_Norm(Wa) < Epsilon)) { fprintf(stderr, "4D up, over and view vectors are not perpendicular\n"); Process.Exit¦(1); } Wa = r4_Scale(1.0/r4_Norm(Wa), Wa); /* Calculate Wb, the perpendicularized Up vector. */ Wb = r4_cross(Over4,Wd,Wa); if ((r4_Norm(Wb) < Epsilon)) { fprintf(stderr, "Invalid 4D over vector\n"); Process.Exit¦(1); } Wb = r4_Scale(1.0/r4_Norm(Wb), Wb); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ Wc = r4_cross(Wd,Wa,Wb); } /* END CalcV4Matrix */ Coords3D_t *ProjectTo3D(ElemTableRec_t *top, Coords_t *c, double scale; )== /* This procedure project all nodes of a configuration from R4 to R3, such that permit to create 3D coordinate needs for the "DisplayConfigura- tion" procedure. */ r3_t ProjectNodeTo3D(co: r4_t) /* Project one 4D node to 3D. This projection is simples in the sense that only permit 4D parallel projection and not perspective. */ r3_t c3 ; { ??? TempV = r4_Sub(co; with (From4), double rtemp = 1.0/Data4Radius ){ c3[0] = scale * rtemp * r4_dot(TempV, Wa); c3[1] = scale * rtemp * r4_dot(TempV, Wb); c3[2] = scale * rtemp * r4_dot(TempV, Wc); return c3; } } ProjectNodeTo3D; void MaxRadius( *ElemTableRec_t *top; Coords_t *c; *ctr: r4_t; ) { for (i = 0; i < top->node.ne; i++) { assert(OrgV(top->node[i])->num == i); Node_t v = OrgV(top->node[i]); ??? Temp4 = r4_Sub(c[v->num]; with (ctr), dist == r4_dot(Temp4, Temp4) ){ if (dist > Data4Radius){ Data4Radius = dist;} } }; } MaxRadius; Coords_t *3D c3D ; nc : uint = (c.ne); { MaxRadius(top,c,To4); c3D = NEW(REF Coords3D_t, nc); for (i = 0; i < nc; i++) { c3D^[i] = ProjectNodeTo3D(c[i]); } return c3D; } /* END ProjectTo3D */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-nPasses"))) { o->nPasses = argparser_get_next_int(pp, 1, 99999); } else { o->nPasses = 1 } argparser_get_keyword(pp, "-maxEvals"); o->maxEvals = argparser_get_next_int(pp, 1, 999999); if (o->nPasses > 1) { if ((argparser_keyword_present(pp, "-nodesPerPass"))) { o->nodesPerPass = argparser_get_next_int(pp, 1, (uint.ne-1)); } else { o->nodesPerPass = (uint.ne-1) } } else { o->nodesPerPass = (uint.ne-1) } if ((argparser_keyword_present(pp, "-writeEvery"))) { o->writeEvery = argparser_get_next_int(pp, 0, 1000000) } else if ((argparser_keyword_present(pp, "-writeAll"))){ o->writeEvery = 1 } else { o->writeEvery = (uint.ne-1) } if ((argparser_keyword_present(pp, "-printEvery"))) { o->printEvery = argparser_get_next_int(pp, 0, 1000000) } else { o->printEvery = (uint.ne-1) } o->showAll = argparser_keyword_present(pp, "-showAll"); o->showBest = (NOT o->showAll)) && (argparser_keyword_present(pp, "-showBest"); if ((o->showAll) || (o->showBest)) { o->wait = argparser_keyword_present(pp, "-wait"); if ((argparser_keyword_present(pp, "-scale"))) { o->scale = pp.getNextLongReal(0.10, 100.00); } else { o->scale = 1.0; } o->wait = FALSE; } o->only3D = argparser_keyword_present(pp, "-only3D"); o->complete = argparser_keyword_present(pp, "-complete"); o->eFunction = ParseEnergyParams.Parse(pp); if (o->eFunction == NULL) { argparser_error(pp, "no energy specified") } o->minimizer = ParseMinimizerParams.Parse(pp); if (o->minimizer == NULL) { argparser_error(pp, "no minimizer specified") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: \\\n"); fprintf(stderr, " OptShape -inFileTp \\\n"); fprintf(stderr, " -inFileSt -outFile \\\n"); fprintf(stderr, " -maxEvals \\\n"); fprintf(stderr, " [-nPasses [ -nodesPerPass ] ] [-only3D]\\\n"); fprintf(stderr, " [-writeEvery | -writeAll ] \\\n"); fprintf(stderr, " [-printEvery ] \\\n"); fprintf(stderr, " [ [ -showAll | -showBest ] [-wait] [-scale]\\\n"); fprintf(stderr, " [-complete ]\\\n"); fprintf(stderr, ParseMinimizerParams.Help); fprintf(stderr, " \\\n"); fprintf(stderr, ParseEnergyParams.Help); fprintf(stderr, "\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } OptShape. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/ProjectTo3D.c #define PROG_NAME "ProjectTo3D" #define PROG_DESC "???" #define PROG_VERS "1.0" #define ProjectTo3D_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Projects a 4D configuration to 3D using the 4D viewing parameters as expected by the "Wire4" - Interactive 4D Wireframe Display Program.*/ #define ProjectTo3D_C_author \ "Modified by L.A.P.Lozada on 2000-02-25." // #INCLUDE // #INCLUDE #include // #INCLUDE #include #include #include // #INCLUDE #include // #INCLUDE CONST double Epsilon = 0.0000000001; TYPE double Coords4D = Triangulation.Coords_t; double Coords3D_t = Tridimensional.Coords3D_t; typedef struct Options_t { char *inFileTp; char *inFileSt; char *outFile; bool_t oblique; /* TRUE == sets From4 at specified angle from mean normal. */ double obliqueAngle; /* (if "oblique") Angle between From4 and mean normal, or . */ bool_t adjustCenter; /* TRUE == translates the model to the origin before projection. */ bool_t adjustScale; /* TRUE == scales model so that it fits in a sphere of radius 1. */ bool_t perspective; /* TRUE == uses perspective projection. */ bool_t statistics; /* TRUE == shows model statistics. */ bool_t printDepth; /* TRUE == prints 4D depth of every node. */ /* 4D viewing parameters */ From4: r4_t; /* Observer position in R^4. */ To4: r4_t; /* Center of attention in R^4. */ Up4: r4_t; /* Z coordinate of projection space. */ Over4: r4_t; /* Y coordinate of projection space. */ Vangle4: double; /* Viewing angle. */ } PROCEDURE WL(double x) : char *== { return(Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 4), 8)); } /* END WL */ PROCEDURE WL4(*x: r4_t) : char *== { return WL(x[0]) & " " & WL(x[1]) & " " & WL(x[2]) & " " & WL(x[3]); } /* END WL4 */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ char *newcmt; { fprintf(stderr, "--------------------------------------------------\n"); ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); with ( c == rc^, double rc3 = NEW(REF Tridimensional.Coords3D_t, top->node.ne), c3 == rc3^; double cmt = tc.cmt & "\nProjectTo3D on " & Today() & "\noptions: " \ "\n -outFile " & o->outFile \ "\n -projection " & ARRAY bool_t OF char *{"parallel", "perspective"}[o->perspective], double bar = Triangulation.Barycenter(top, c, all = FALSE); double norm = MeanNorm(top, c); double meanRadius = MeanRadius(top, c, bar); double meanThickness = MeanThickness(top, c, bar, norm) ){ fprintf(stderr, "Model shape parameters (before normalization and projection):\n"); fprintf(stderr, " normal == ( " & WL4(norm) & ")\n"); fprintf(stderr, " mean radius == " & WL(meanRadius) & "\n"); fprintf(stderr, " mean thickness == " & WL(meanThickness) & "\n"); fprintf(stderr, " rel. thickness == " & WL(meanThickness/meanRadius) & "\n"); if (o->oblique) { /* Places "From4" so that "From4-To4" is oblique to the mean normal */ SelectObliqueProjection(o, norm, o->obliqueAngle); newcmt = cmt & "\n -oblique " & WL(o->obliqueAngle); } if (o->adjustCenter) { /* Move figure so that barycenter is at origin */ for (i = 0 TO (c.ne-1)){ c[i] = r4_Sub(c[i], bar); } newcmt = cmt & "\n -adjustCenter"; } if (o->adjustScale) { /* Adjust scale of figure so that it fits in a sphere of radius 1 centered at To4 */ ??? maxRadius = MaxRadius(top, c, o->To4); { for (i = 0 TO (c.ne-1)){ c[i] = r4_Scale(1.0/maxRadius, c[i]);} } newcmt = cmt & "\n -adjustScale"; } newcmt = cmt & "\nparameters: " \ "\n -From4 " & WL4(o->From4) \ "\n -To4 " & WL4(o->To4) \ "\n -Up4 " & WL4(o->Up4) \ "\n -Over4 " & WL4(o->Over4) \ "\n -Vangle4 " & WL(o->Vangle4); ProjectTo3D(o, c, c3, top); if (o->statistics) { ShowStatistics(top, c, c3) } WriteState3D(o->outFile, top, c3, newcmt) } fprintf(stderr, "--------------------------------------------------\n") } /* END DoIt */ double MaxRadius(ElemTableRec_t *top, *c: Coords4D; *ctr: r4_t) radius = 0.0; { for (i = 0; i < top->node.ne; i++){ assert(OrgV(top->node[i])->num == i); ??? d = r4_Dist(ctr; with ( c[i]) ){ if (d > radius){ radius = d;} } } return radius; } /* END MaxRadius */ double MeanRadius(ElemTableRec_t *top, *c: Coords4D; *bar: r4_t) sum2 : double = 0.0; { for (i = 0; i < top->node.ne; i++){ ??? di = r4_Dist(c[i]; with (bar) ){ sum2 = sum2 + di*di; } } return sqrt(sum2/FLOAT(top->node.ne-1,double)); } /* END MeanRadius */ double MeanThickness(ElemTableRec_t *top, *c: Coords4D; *bar, norm: r4_t) sum2 : double = 0.0; { for (i = 0; i < top->node.ne; i++){ ??? di = r4_dot(r4_Sub(c[i]; with (bar),norm) ){ sum2 = sum2 + di*di; } } return sqrt(sum2/FLOAT(top->node.ne-1,double)); } /* END MeanThickness */ r4_t MeanNorm(ElemTableRec_t *top, *c: Coords4D) norm: r4_t = (r4_t){0.0, ..}; { for (i = 0; i < top->cell.ne; i++){ ??? f = Srot(top.cell[i]); ??? k = TetrahedronNodes(f); ??? p = c[k[0]]; ??? q = c[k[1]]; ??? r = c[k[2]]; ??? s = c[k[3]]; ??? pq = r4_Sub(q; with ( p), double pr = r4_Sub(r, p); double ps = r4_Sub(s, p); double v = r4_cross(pq, pr, ps); double n = r4_Dir(v) ){ norm = r4_Add(norm, n) } } ??? m = r4_Norm(norm); { if (m < 1.0d-20) { return (r4_t){1.0, 0.0, ..}; } else { return r4_Scale(1.0/m, norm); } } } /* END MeanNorm */ PROCEDURE ProjectTo3D( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); *c: Coords4D; VAR c3: Tridimensional.Coords3D_t; *ElemTableRec_t *top; ) void CalcV4Matrix() /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ double *norm; { /* Calculate Wd, the 4th coordinate basis vector and line-of-sight. */ Wd = r4_Sub(o->To4,o->From4); norm = r4_Norm(Wd); if (norm < Epsilon) { fprintf(stderr,"4D To Point and From Point are the same\n"); Process.Exit¦(1); } Wd = r4_Scale(1.0/norm, Wd); /* Calculate Wa, the X-axis basis vector. */ Wa = r4_cross(o->Up4,o->Over4,Wd); norm = r4_Norm(Wa); if (norm < Epsilon) { fprintf(stderr, "4D up,over and view vectors are not perpendicular\n"); Process.Exit¦(1); } Wa = r4_Scale(1.0/norm, Wa); /* Calculate Wb, the perpendicularized Up vector. */ Wb = r4_cross(o->Over4,Wd,Wa); norm = r4_Norm(Wb); if (norm < Epsilon) { fprintf(stderr,"Invalid 4D over vector\n"); Process.Exit¦(1); } Wb = r4_Scale(1.0/norm, Wb); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ Wc = r4_cross(Wd,Wa,Wb); } CalcV4Matrix; VAR double rtemp; Wa,Wb,Wc,Wd : r4_t; { ??? angle = o->Vangle4/2.0; ??? angler = (FLOAT(Math.Pi, double)*angle)/180.0); with( double tan2vangle4 = Math.tan(angler); double pconst = 1.0 / tan2vangle4 ){ CalcV4Matrix(); for (i = 0; i < top->node.ne; i++) { /* Transform the nodes from 4d World coordinates to 4D eye coordinates. */ Node_t v = OrgV(top->node[i]); ??? t = r4_Sub(c[v->num]; with (o->From4), double depth = r4_dot(t,Wd) DO if (o->printDepth) { fprintf(stderr, "v[" & Fmt.Pad(Fmt.Int(v->num),4) & "] depth == " \ Fmt.Pad(Fmt.LongReal(depth, Fmt.Style.Fix, prec = 4),8) & "\n" ) } if (o->perspective){ rtemp = pconst / depth }else{ rtemp = 1.0; } c3[v->num][0] = rtemp * r4_dot(t, Wa); c3[v->num][1] = rtemp * r4_dot(t, Wb); c3[v->num][2] = rtemp * r4_dot(t, Wc); } } } } /* END ProjectTo3D */ PROCEDURE SelectObliqueProjection( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); *norm: r4_t; double angle; ) CONST Pi == M_PI; { ??? rad = Pi/180.0 * angle; ??? c = Math.cos(rad); ??? s = Math.sin(rad); ??? dir = r4_Dir(r4_Mix(c; with ( norm, s, Perp(norm))) ){ o->From4 = r4_Add(o->To4, r4_Scale(6.0, dir)) } SelectTwoIndepDirs(norm, o->Up4, o->Over4); } /* END SelectObliqueProjection */ r4_t Perp(v: r4_t) /* Returns a vector perpendicular to "v" */ uint *r; double s = 0.0; VAR { /* Find largest coordinate */ r = 0; for (i = 1; i < 4; i++){ if ((fabs(v[i]) > fabs(v[r]))){ r = i; } } if ((fabs(v[r]) > 0.0)) { /* Compute new value for it */ for (i = 0; i < 4; i++){ if (i != r){ s = s + v[i]*v[i]; } } v[r] = - s / v[r]; } return v; } /* END Perp */ PROCEDURE SelectTwoIndepDirs( *u: r4_t; VAR v, w: r4_t; ) /* Selects two vectors "v", "w", independent of each other and of the given vector "u". */ m: uint = 0; { /* Find the largest coordinate of "u": */ for (i = 1; i < 4; i++){ if ((fabs(u[i]) > fabs(u[m]))){ m = i; } } for (i = 0; i < 4; i++){ v[i] = 0.0; w[i] = 0.0; } v[(m+1) % 4] = 1.0; w[(m+2) % 4] = 1.0; } /* END SelectTwoIndepDirs */ PROCEDURE ShowStatistics(ElemTableRec_t *top; *c: Coords4D; *c3: Coords3D_t) { Analyze@{Edge->?}s(top, c); AnalyzeWalls(top, c, c3); AnalyzeCells(top, c, c3); } /* END ShowStatistics */ PROCEDURE Analyze@{Edge->?}s(ElemTableRec_t *top, *c: Coords4D) == stl: Stat.T; { fprintf(stderr, "Statistics for existing @{edge->?}s:\n"); Stat.Init(stl); for (i = 0; i < top->NE; i++) { with (e == top->edge[i]) { if (e->exists) { ??? p = e.pa; Node_t un = OrgV(p)->num; Node_t vn = OrgV(Clock(p))->num; ??? l = r4_Dist(c[un]; with (c[vn]), double ll = FLOAT(l, REAL) ){ Stat.Accum(stl, ll) } } } } fprintf(stderr, " lengths in R^4: "); Stat.Print(stderr, stl); fprintf(stderr, "\n"); } /* END Analyze@{Edge->?}s */ PROCEDURE AnalyzeWalls(ElemTableRec_t *top, *c: Coords4D; *c3: Coords3D_t) sta: Stat.T; { fprintf(stderr, "Statistics for existing walls:\n"); Stat.Init(sta); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists) { ??? p = f.pa, double un = OrgV(p)->num; double vn = OrgV(NextE(p))->num; double wn = OrgV(PrevE(p))->num; double a = r4_Dist(c[vn],c[un]); double b = r4_Dist(c[wn],c[un]); double c = r4_Dist(c[vn],c[wn]); double p = (a+b+c); double s = 0.5 * p; double sa = s - a; double sb = s - b; double sc = s - c; double ar = sqrt(MAX(s*sa*sb*sc, 0.0)); double arr = FLOAT(ar, REAL) ; { Stat.Accum(sta, arr) } } } } fprintf(stderr, " areas in R^4: "); Stat.Print(stderr, sta); fprintf(stderr, "\n"); ??? ns = CountSilhouetteWalls(top; with (c3), double nb = CountBorderWalls(top); double nn = top->wall.ne-ns-nb ){ fprintf(stderr, " projection to R^3:" \ " silhouette == " & Fmt.Int(ns) \ " border == " & Fmt.Int(nb) \ " normal == " & Fmt.Int(nn) & "\n"); } } /* END AnalyzeWalls */ PROCEDURE AnalyzeCells(ElemTableRec_t *top, *c: Coords4D; *c3: Coords3D_t) stv: Stat.T; { fprintf(stderr, "Statistics for existing tetrahedra:\n"); Stat.Init(stv); for (i = 0; i < top->cell.ne; i++) { ??? r = Srot(top.cell[i]), t == PnegP(Tors(r)); { if (t->exists) { ??? vt = TetrahedronNodes(r); ??? un = vt[0]; ??? vn = vt[1]; ??? wn = vt[2]; ??? xn = vt[3]; ??? uv = r4_Sub(c[vn]; with (c[un]), double uw = r4_Sub(c[wn],c[un]); double ux = r4_Sub(c[xn],c[un]); double n = r4_cross(uv, uw, ux); double v = 1.0/6.0 * r4_Norm(n); double vv = FLOAT(v, REAL) ){ Stat.Accum(stv, vv) } } } } fprintf(stderr, " volume in R^4: "); Stat.Print(stderr, stv); fprintf(stderr, "\n"); ??? nn = CountNegativeTetrahedra(top; with (c3), double np = top->cell.ne - nn ){ fprintf(stderr, " projection to R^3:" \ " negative == " & Fmt.Int(nn) \ " positive == " & Fmt.Int(np) & "\n"); } } /* END AnalyzeCells */ /* PROCEDURE CountBorder@{Edge->?}s(ElemTableRec_t *top) : uint == count : uint = 0; { for (i = 0; i < top.edge.ne; i++){ if ((Triangulation.EdgeIsBorder(top.edge[i].pa))){ count++; } } return count; } CountBorder@{Edge->?}s; PROCEDURE CountMiswound@{Edge->?}s(ElemTableRec_t *top; *c3: Coords3D_t) : uint == count: uint = 0; { for (i = 0; i < top.edge.ne; i++){ ??? a = top.edge[i].pa; { if ((! Triangulation.EdgeIsBorder(a))) { ??? wnd = Tridimensional.edgeWindingNumber(a, c3); { if ((fabs(wnd)!=1)) { fprintf(stderr, " @{edge->?} " & Fmt.Int(i)); fprintf(stderr, " winding number == " & Fmt.Int(wnd) & "\n"); count++ } } } } } return count; } CountMiswound@{Edge->?}s; */ uint CountSilhouetteWalls(ElemTableRec_t *top; *c3: Coords3D_t) bool_t WallIsSilhouette(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall */ { if ((Ppos(a) == NULL) || (Pneg(a) == NULL)){ return FALSE; } ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; ??? d1 = TetraDet3D(un; with (vn,wn,xn, c3), double d2 = TetraDet3D(un,vn,wn,yn, c3) ){ return d1*d2 >= 0.0; } } WallIsSilhouette; count : uint = 0; { for (i = 0; i < top.wall.ne; i++){ if ((WallIsSilhouette(top.wall[i].pa))){ count++; } } return count; } CountSilhouetteWalls; uint CountBorderWalls(ElemTableRec_t *top) bool_t WallIsBorder(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a border wall, FALSE c.c. */ { return Ppos(a) == NULL) || (Pneg(a) == NULL; } WallIsBorder; count : uint = 0; { for (i = 0; i < top.wall.ne; i++){ if ((WallIsBorder(top.wall[i].pa))){ count++; } } return count; } CountBorderWalls; uint CountNegativeTetrahedra(ElemTableRec_t *top; *c3: Coords3D_t) count : uint = 0; { ??? t = Triangulation.CollectTetrahedra(top)^; { for (i = 0; i < top.cell.ne; i++) { ??? a = t[i]; Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(PrevF(a)))->num DO if ((TetraDet3D(un; with (vn,wn,xn, c3) <= 0.0)){ count++; } } } } return count; } CountNegativeTetrahedra; PROCEDURE TetrahedronNodes(f:TriangulationPlace_t): ARRAY [0..3] OF uint == /* Returns the nodes of a cell, given a dual wedge "f" with origin at the cell's center. Assumes that the cell is a tetrahedron. */ { Place_t g = Tors(f); Place_t h = Tors(Clock(PrevE(f))); ??? p = Org(g)->num; ??? q = Org(NextE(g))->num; ??? r = Org(PrevE(g))->num; ??? s = Org(PrevE(h))->num; { return ARRAY [0..3] OF uint {p, q, r, s}; } } /* END TetrahedronNodes */ double TetraDet3D(uint u, uint v, uint w, uint x, Coords3D_t *c3) /* For each tetrahedron with nodes numbers u,v,w,x computes its orientation in R^{3} through the 4x4 determinant: _ _ | c3[u][0] c3[u][1] c3[u][2] 1.0 | double B = | c3[v][0] c3[v][1] c3[v][2] 1.0 | | c3[w][0] c3[w][1] c3[w][2] 1.0 | | c3[x][0] c3[x][1] c3[x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[u][0], c3[u][1], c3[u][2], 1.0}; double b = (r4_t){c3[v][0], c3[v][1], c3[v][2], 1.0}; double c = (r4_t){c3[w][0], c3[w][1], c3[w][2], 1.0}; double d = (r4_t){c3[x][0], c3[x][1], c3[x][2], 1.0} ){ return r4_det(a,b,c,d); } } /* END TetraDet3D */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } argparser_get_keyword(pp, "-projection"); ??? pname = argparser_get_next(pp); { if (0 == strcmp(pname, "Parallel"))) { o->perspective = FALSE } else if (0 == strcmp(pname, "Perspective"))){ o->perspective = TRUE } else { argparser_error(pp, "Bad projection \"" & argparser_get_next(pp) & "\"\n") } } o->adjustCenter = argparser_keyword_present(pp, "-adjustCenter"); o->adjustScale = argparser_keyword_present(pp, "-adjustScale"); if ((argparser_keyword_present(pp, "-oblique"))) { o->oblique = TRUE; o->obliqueAngle = pp.getNextLongReal(-180.0, +180.0); } else { o->oblique = FALSE; if ((argparser_keyword_present(pp, "-From4"))) { for (j = 0; j < 4; j++) { o->From4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From4 = (r4_t){0.0,0.0,0.0,-3.0}; } } if ((argparser_keyword_present(pp, "-To4"))) { for (j = 0; j < 4; j++) { o->To4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To4 = (r4_t){0.0,0.0,0.0,0.0}; }; if ((argparser_keyword_present(pp, "-Up4"))) { for (j = 0; j < 4; j++) { o->Up4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up4 = (r4_t){0.0,1.0,0.0,0.0}; }; if ((argparser_keyword_present(pp, "-Over4"))) { for (j = 0; j < 4; j++) { o->Over4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Over4 = (r4_t){0.0,0.0,1.0,0.0}; }; if ((argparser_keyword_present(pp, "-Vangle4"))) { o->Vangle4 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle4 = 25.0; } o->statistics = argparser_keyword_present(pp, "-statistics"); o->printDepth = argparser_keyword_present(pp, "-printDepth"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage:\n" \ " ProjectTo3D -inFileTp \\\n" \ " -inFileSt [ -outFile ] \\\n" \ " -projection [ Perspective | Parallel ]\\\n" \ " [ -adjustCenter ] [ -adjustScale ] \\\n" \ " [ -oblique ANGLE | -From4 ] \\\n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ] \\\n" \ " [ -Vangle4 ] \\\n" \ " [ -statistics ] \\\n" \ " [ -printDepth ] \n"); END¦ } } return o; } /* END GetOptions */ /* end ProjectTo3D */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/RandomShape.c #define PROG_NAME "RandomShape" #define PROG_DESC "???" #define PROG_VERS "1.0" #define RandomShape_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This module generates N random variations (trials) of a given ".tp" file. Reused without extensive modifications, created originally by J. Stolfi and R. Marcone. */ #define RandomShape_C_author \ "Created originally by J. Stolfi and R. M. Rosi for 2D maps.\n" \ "Modified by L.A.P.Lozada on 02-12-1999." // #INCLUDE #include // #INCLUDE #include #include TYPE typedef struct Options_t { char *input; /* Input file name (minus ".tp" extension) */ char *output; /* Output file name prefix */ uint trialMin; /* Number of first configuration to generate */ uint trialMax; /* Number of last configuration to generate */ REAL jitter; /* Magnitude of random perturbation */ bool_t normalize; /* TRUE to normalize the node coordinates */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) char **cmt; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? coins = NEW(Random.Default).init(TRUE); ??? tc = Triangulation.ReadToMa(o->input); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->input); ??? cOld = rc^; ??? cNew = NEW(REF Coords_t; with ( top->node.ne)^ ){ if (o->normalize) { Triangulation.NormalizeNodeDistances(top, cOld, TRUE) } for (k = o->trialMin; k <= (o->trialMax); k++) { cNew = cOld; PerturbCoords(top, cNew, coins, ((double)o->jitter)); if (o->normalize) { Triangulation.NormalizeNodeDistances(top, cNew, TRUE) } cmt = " Random variation Number: " & Fmt.Int(k) & "\n" \ " Randomizing from: " & o->input & ".top\n" & " Created by RandomShape: " & o->output & "-" \ Fmt.Pad(Fmt.Int(k), 2, '0') & ".tp\n"; WriteState(o->output & "-" & Fmt.Pad(Fmt.Int(k),2,'0'), top,cNew,cmt & "\nRandom Geometry") } return 0; } PROCEDURE PerturbCoords(ElemTableRec_t *top, Coords_t *c, rand_t *coins; double jitter; ) { for (i = 0 TO (c.ne-1)){ if ((OrgV(top->node.e[i])->exists) && (NOT top->node[i].fixed)) { ??? ci = c[i]; with ( double p = (r4_t) { jitter * coins.longreal(-1.0, +1.0), jitter * coins.longreal(-1.0, +1.0), jitter * coins.longreal(-1.0, +1.0), jitter * coins.longreal(-1.0, +1.0) } ){ ci = r4_Add(ci, p); } } } } /* END PerturbCoords */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-input"); o->input = argparser_get_next(pp); argparser_get_keyword(pp, "-output"); o->output = argparser_get_next(pp); argparser_get_keyword(pp, "-trials"); o->trialMin = argparser_get_next_int(pp, 0); o->trialMax = argparser_get_next_int(pp, o->trialMin); o->normalize = argparser_keyword_present(pp, "-normalize"); if ((argparser_keyword_present(pp, "-jitter"))) { o->jitter = pp.getNextReal(0.0); } else { o->jitter = 1.0 } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: RandomShape \\\n" \ " -input -output \\\n" \ " -trials \\\n" \ " [ -normalize ] [ -jitter ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } RandomShape. /* Comments -------- The procedure "Triangulation.NormalizeNodeDistance", normalizes the distances such that the average distance to origin is ever "one". If the attribute NORMALIZE == FALSE (i.e. absent), then the coordinates may to change between [-10,+10], according to the "jitter" value chose. If the attribute NORMALIZE == TRUE (i.e. present), then the coordinates are independent of the "jitter" value chose and may change between [-1,+1], may be occur that some coordinates to make off from this limits, but in geral, the majority are on this limits. ***************** START OF COPYRIGHT) && (AUTHORSHIP NOTICE ********** All files in this directory tree are Copyright 1996 by Jorge Stolfi, Rober Marcone Rosi, and Universidade Estadual de Campinas, Brazil--- unless stated otherwise in the files themselves. THESE FILES ARE DISTRIBUTED with (NO GUARANTEE OF ANY KIND. Neither the authors nor their employers may be held responsible for any losses or damages attributed to their use. These files may be freely copied, distributed, modified, and used for any purpose; provided that any subtantial excerpt of these files that is redistributed or incorporated in other software packages is accompanied by this copyright and authorship notice, and is made freely available under these same terms. *****************;} OF COPYRIGHT) && (AUTHORSHIP NOTICE ************ */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/RawCubeTriang.c #define PROG_NAME "RawCubeTriang" #define PROG_DESC "???" #define PROG_VERS "1.0" #define RawCubeTriang_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Creates ".tp",".tb",".st" and ".ma" files for one triangulated cube of order "gridOrder" with fixed geometry. The cube have six places saved. */ #define RawCubeTriang_C_author \ "Implemented by L. Lozada, 1999-2000." // #INCLUDE // #INCLUDE #include // #INCLUDE #include #include #include // // #INCLUDE // #INCLUDE TYPE typedef struct Options_t { uint gridOrder; } PROCEDURE Main() { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? co = MakeCubeTriang(o->gridOrder); ElemTableRec_t top = MakeElemTable(co.e[0], 1), double c = ComputeCoordinates(co, top, o->gridOrder)^; double cmt = " Individual triangulated cube with fixed geometry\n" & " Created by MakeRawCubeTriang: cubetriang-" \ Fmt.Int(o->gridOrder) & ".ct\n" ){ WriteTopology( "cubetriang-" & Fmt.Int(o->gridOrder), top, cmt & Today()); MakeElemTableTable( "cubetriang-" & Fmt.Int(o->gridOrder), top, cmt & Today()); WriteState( "cubetriang-"&Fmt.Int(o->gridOrder),0.0,top,c,cmt & Today()); WriteMaterials( "cubetriang-" & Fmt.Int(o->gridOrder), top,cmt& Today()); } } /* END Main */ Coords_t *ComputeCoordinates( *Place_t co.e[5+1]; ElemTableRec_t *top; uint order; )== { ??? r = NEW(REF Coords_t; with ( top.node.ne), double c = r^; double o0 = (r4_t){-1.0,-1.0,-1.0,0.0}; double o1 = (r4_t){ 1.0,-1.0,-1.0,0.0}; double o2 = (r4_t){-1.0, 1.0,-1.0,0.0}; double o3 = (r4_t){ 1.0, 1.0,-1.0,0.0}; double o4 = (r4_t){-1.0,-1.0, 1.0,0.0}; double o5 = (r4_t){ 1.0,-1.0, 1.0,0.0}; double o6 = (r4_t){-1.0, 1.0, 1.0,0.0}; double o7 = (r4_t){ 1.0, 1.0, 1.0,0.0} ){ void SetCornerCoords(Place_t e, r4_t *cv) { c[OrgV(e)->num] = cv; } SetCornerCoords; PROCEDURE SetCoord@{Edge->?}v1v3(Place_t @p, *o: r4_t) == /* Set the node coordinates along the edge with nodes v1v3. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0], o[1]+x, o[2], o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a, FLOAT(i,double) *2.0/FLOAT(order,double)); } } SetCoord@{Edge->?}v1v3; PROCEDURE SetCoord@{Edge->?}v3v2(Place_t @p, *o: r4_t) == /* Set the node coordinates along the edge with nodes v3v2. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0]-x, o[1], o[2], o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a, FLOAT(i,double) *2.0/FLOAT(order,double)); } } SetCoord@{Edge->?}v3v2; PROCEDURE SetCoord@{Edge->?}v2v6(Place_t @p, *o: r4_t) == /* Set the node coordinates along the edge with nodes v2v6. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0], o[1], o[2]+x, o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a, FLOAT(i,double) *2.0/FLOAT(order,double)); } } SetCoord@{Edge->?}v2v6; PROCEDURE SetCoord@{Edge->?}v6v4(Place_t @p, *o: r4_t) == /* Set the node coordinates along the edge with nodes v6v4. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0], o[1]-x, o[2], o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a, FLOAT(i,double) *2.0/FLOAT(order,double)); } } SetCoord@{Edge->?}v6v4; PROCEDURE SetCoord@{Edge->?}v4v5(Place_t @p, *o: r4_t) == /* Set the node coordinates along the edge with nodes v4v5. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0]+x, o[1], o[2], o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a, FLOAT(i,double) *2.0/FLOAT(order,double)); } } SetCoord@{Edge->?}v4v5; PROCEDURE SetCoord@{Edge->?}v5v1(Place_t @p, *o: r4_t) == /* Set the node coordinates along the edge with nodes v5v1. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0], o[1], o[2]-x, o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextE(a)))); SetNodeCoords(a, FLOAT(i,double) *2.0/FLOAT(order,double)); } } SetCoord@{Edge->?}v5v1; void SetCoordDiagonal(Place_t @p, *o: r4_t) /* Set the node coordinates along the diagonal @{edge->?}. */ void SetNodeCoords(e: Place_t; x: double) { c[OrgV(e)->num] = (r4_t){o[0]+x, o[1]+x, o[2]+x, o[3]}; } SetNodeCoords; { for (i = 1; i < order; i++) { a = Clock(PrevE(NextF(NextF(NextE(a))))); SetNodeCoords(a, FLOAT(i,double) *2.0/FLOAT(order,double)); } SetCornerCoords(Clock(a),o7); } SetCoordDiagonal; Place_t Move(Place_t @p) { return Clock(PrevE(PrevF(PrevE(a)))); } Move; { /* Set the corners */ SetCornerCoords(co.e[0],o0); SetCornerCoords(PrevE(co.e[5]),o1); SetCornerCoords(PrevE(co.e[0]),o3); SetCornerCoords(PrevE(co.e[1]),o2); SetCornerCoords(PrevE(co.e[2]),o6); SetCornerCoords(PrevE(co.e[3]),o4); SetCornerCoords(PrevE(co.e[4]),o5); SetCoord@{Edge->?}v1v3(Move(co.e[5]), o1); SetCoord@{Edge->?}v3v2(Move(co.e[0]), o3); SetCoord@{Edge->?}v2v6(Move(co.e[1]), o2); SetCoord@{Edge->?}v6v4(Move(co.e[2]), o6); SetCoord@{Edge->?}v4v5(Move(co.e[3]), o4); SetCoord@{Edge->?}v5v1(Move(co.e[4]), o5); SetCoordDiagonal(co.e[0],o0); } return r; } } ComputeCoordinates; PROCEDURE MakeCubeTriang(gridOrder: uint) : SixPlaces_t == VAR Place_t co.e[5+1]; { ??? ca = MakeTetraTopo(gridOrder; with (gridOrder), double cb = MakeTetraTopo(gridOrder,gridOrder); double cc = MakeTetraTopo(gridOrder,gridOrder); double cd = MakeTetraTopo(gridOrder,gridOrder); double ce = MakeTetraTopo(gridOrder,gridOrder); double cf = MakeTetraTopo(gridOrder,gridOrder); double bc1 = ca.e[0], ac1 == Spin(cb.e[1]); double bc2 = cb.e[0], ac2 == Spin(cc.e[1]); double bc3 = cc.e[0], ac3 == Spin(cd[1]); double bc4 = cd[0], ac4 == Spin(ce[1]); double bc5 = ce[0], ac5 == Spin(cf[1]); double bc6 = cf[0], ac6 == Spin(ca.e[1]) ){ EVAL Triangulation.Glue(ac1,bc1,gridOrder); EVAL Triangulation.Glue(ac2,bc2,gridOrder); EVAL Triangulation.Glue(ac3,bc3,gridOrder); EVAL Triangulation.Glue(ac4,bc4,gridOrder); EVAL Triangulation.Glue(ac5,bc5,gridOrder); EVAL Triangulation.Glue(ac6,bc6,gridOrder); co.e[0] = cb.e[1]; co.e[1] = cc.e[1]; co.e[2] = cd[1]; co.e[3] = ce[1]; co.e[4] = cf[1]; co.e[5] = ca.e[1]; fprintf(stderr, "Exit MakeCubeTriang: \n"); return co; } } /* END MakeCubeTriang */ /* UNUSED */ Place_t GlueCubeTriang(a, b : Place_t; n: uint) ta,Place_t tb[100+1]; { assert(SpinBit(a) == SpinBit(b)); /* sanity check */ assert(n >= 1); ta[0] = a; tb[0] = b; for (i = 1; i < 2*n; i++) { ta[i] = Clock(PrevE(NextF(NextE(ta[i-1])))); tb[i] = Clock(PrevE(PrevF(NextE(tb[i-1])))); assert(ta[i]!=a); assert(tb[i]!=b); } Meld(b, a); /* Update the edge slots for i==0 */ SetRingEdgeInfo(a, PEdge(a)); SetRingEdgeInfo(NextE(a), PEdge(NextE(a))); SetRingEdgeInfo(PrevE(a), PEdge(PrevE(a))); /* Update the node slots for i==0 */ SetOrgAll(a, OrgV(a)); SetOrgAll(Clock(a), OrgV(Clock(a))); SetOrgAll(NextE(a), OrgV(NextE(a))); SetOrgAll(Clock(NextE(a)), OrgV(Clock(NextE(a)))); SetOrgAll(PrevE(a), OrgV(PrevE(a))); SetOrgAll(Clock(PrevE(a)), OrgV(Clock(PrevE(a)))); for (i = 1; i < 2*n; i++) { Meld(tb[i],ta[i]); /* Update the edge slots */ SetRingEdgeInfo(ta[i], PEdge(ta[i])); SetRingEdgeInfo(NextE(ta[i]), PEdge(NextE(ta[i]))); SetRingEdgeInfo(PrevE(ta[i]), PEdge(PrevE(ta[i]))); /* Update the node slots */ SetOrgAll(ta[i], OrgV(ta[i])); SetOrgAll(Clock(ta[i]), OrgV(Clock(ta[i]))); SetOrgAll(NextE(ta[i]), OrgV(NextE(ta[i]))); SetOrgAll(Clock(NextE(ta[i])), OrgV(Clock(NextE(ta[i])))); SetOrgAll(PrevE(ta[i]), OrgV(PrevE(ta[i]))); SetOrgAll(Clock(PrevE(ta[i])), OrgV(Clock(PrevE(ta[i])))); } SetOrgAll(Clock(PrevE(PrevF(PrevE(ta[n-1])))), Org(PrevE(a))); return ta[n-1]; } /* END GlueCubeTriang */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-gridOrder"); o->gridOrder = argparser_get_next_int(pp, 1, 20); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeRawCubeTriang -gridOrder \n"); END¦ } } return o; } /* END GetOptions */ { Main(); } RawCubeTriang. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/RefineTriang.c #define PROG_NAME "RefineTriang" #define PROG_DESC "???" #define PROG_VERS "1.0" #define RefineTriang_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Refines (or duplicate) a given triangulation (".tp" file). See notice of copyright at the end of this file. Revisions: 21-05-2000: Fixed and removed a bug that increases the number of original nodes of type \"VV\". 31-05-2000: Added the heredity of the "root" attributes for edges and walls. 11-06-2000: Hide the new elements insert in the refiment process: @{edge->?}s and nodes are set with the attibute "exists== FALSE" 25-11-2000: Added the option "net" for simulate textures on existing walls with thin cylinders and small spheres. */ #include #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // Coords_t, Node, OrgV, Makewedge, MakeNode, SetOrg, Org, Pneg, Ppos, MakeCell, Wedge_t, @{Node->?}, SetOrgAll, SetPnegOfWall; // #INCLUDE // Place_t, Tors, Spin, Clock, NextF, SpinBit, OrientationBit, SpliceEdges, NextE, SetNextF, SetNextE, SetWallInfo, PrevE, SetEdgeInfo, PrevF, SetRingEdgeInfo, Srot, SetRingWallInfo; REF Node_vec_t x ; NNV: uint = 0; TYPE typedef struct Options_t { char *inFileTp; /* Input file name (minus ".tp" extension) */ char *inFileSt; /* Input file name (minus ".st" extension) */ char *outFile; /* Output file name prefix */ bool_t fixOri; /* TRUE to fix original nodes */ bool_t assert; /* make some strong assertions */ bool_t net; /* simulate a net as small spheres and thin cylinders. */ } double RowT = ARRAY [0..3] OF Place_t; CONST double Thin@{Edge->?}Exists = FALSE; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) REF ARRAY OF Place_vec_t gi ; n{ ElemTableRec_t top; Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp; with (FALSE), /* TRUE for indicate root of tetrahedra */ top == tc.top, rc == Triangulation.ReadState(o->inFileSt), c == rc^, double half = Place_vec_new(2*top->wall.nelE)^; double vnew = Node_vec_new(top->node.ne)^ ){ for (i = 0; i < top->wall.ne; i++) { if ((Octf.DegreeOfEdge(top->wall[i].pa)!=3)) { fprintf(stderr,"This topology isn't a triangulation\n"); Process.Exit¦(1); } } fprintf(stderr, "Refining from: " & o->inFileTp & ".tp\n"); gi = NEW(REF ARRAY OF Place_vec_t, top->cell.ne, 4); Node_vec_t x = Node_vec_new(top->cell.ne); Place_t Half(Place_t @p) { ??? na = PWedge(a)->num; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? h = half[2*na + oa]; { if (sa == 0){ return h }else{ return Spin(h); } } } Half; /* ====== Refine the Tetrahedral Cell ====== */ void RefineCell(g: RowT; in: uint) { /* To insert four walls obliques "i", "j", "k", "l" */ ??? i = MakeTriangle(FALSE); ??? j = MakeTriangle(FALSE); ??? k = MakeTriangle(FALSE); ??? l = MakeTriangle(FALSE); { /* the wall "i" will be splice with g[1], g[2], g[3] */ SetNextF(i,Clock(g[1])); SetNextF(NextE(i),NextE(g[3])); SetNextF(PrevE(i),Clock(g[2])); /* Update the component @{edge->?} */ SetRingEdgeInfo(i, PEdge(g[1])); SetRingEdgeInfo(NextE(i), PEdge(NextE(g[3]))); SetRingEdgeInfo(PrevE(i), PEdge(g[2])); /* Update the origins */ SetOrg(i, OrgV(g[2])); SetOrg(Clock(i), OrgV(g[1])); SetOrg(NextE(i), OrgV(Clock(i))); SetOrg(Clock(NextE(i)), OrgV(NextE(g[2]))); SetOrg(PrevE(i), OrgV(Clock(NextE(i)))); SetOrg(Clock(PrevE(i)), OrgV(i)); /* the wall "j" will be splice with: g[0], g[1], g[2] */ SetNextF(j,NextE(g[0])); SetNextF(NextE(j),Clock(NextE(g[1]))); SetNextF(PrevE(j),Clock(PrevE(g[2]))); /* Update the component @{edge->?} */ SetRingEdgeInfo(j, PEdge(NextE(g[0]))); SetRingEdgeInfo(NextE(j), PEdge(NextE(g[1]))); SetRingEdgeInfo(PrevE(j), PEdge(PrevE(g[2]))); /* Update the origins */ SetOrg(j, OrgV(NextE(g[0]))); SetOrg(Clock(j), OrgV(PrevE(g[0]))); SetOrg(NextE(j), OrgV(Clock(j))); SetOrg(Clock(NextE(j)), OrgV(g[2])); SetOrg(PrevE(j), OrgV(Clock(NextE(j)))); SetOrg(Clock(PrevE(j)), OrgV(j)); /* the wall "k" will be splice with: g[0], g[1], g[3]) */ SetNextF(k,Clock(PrevF(PrevE(g[0])))); SetNextF(NextE(k),NextF(PrevE(g[1]))); SetNextF(PrevE(k),Clock(PrevF(g[3]))); /* Update the component @{edge->?} */ SetRingEdgeInfo(k,PEdge(PrevE(g[0]))); SetRingEdgeInfo(NextE(k),PEdge(PrevE(g[1]))); SetRingEdgeInfo(PrevE(k),PEdge(g[3])); /* Update the origins */ SetOrg(k, OrgV(g[0])); SetOrg(Clock(k), OrgV(PrevE(g[0]))); SetOrg(NextE(k), OrgV(Clock(k))); SetOrg(Clock(NextE(k)), OrgV(g[1])); SetOrg(PrevE(k), OrgV(Clock(NextE(k)))); SetOrg(Clock(PrevE(k)), OrgV(k)); /* the wall "l" will be splice with: g[0], g[2], g[3] */ SetNextF(l, Clock(PrevF(g[0]))); SetNextF(NextE(l), Clock(PrevF(PrevE(g[3])))); SetNextF(PrevE(l), NextF(NextE(g[2]))); /* Update the component @{edge->?} */ SetRingEdgeInfo(l, PEdge(g[0])); SetRingEdgeInfo(NextE(l), PEdge(PrevE(g[3]))); SetRingEdgeInfo(PrevE(l), PEdge(NextE(g[2]))); /* Update the origins */ SetOrg(l, OrgV(Clock(g[0]))); SetOrg(Clock(l), OrgV(g[0])); SetOrg(NextE(l), OrgV(Clock(l))); SetOrg(Clock(NextE(l)), OrgV(NextE(g[2]))); SetOrg(PrevE(l), OrgV(Clock(NextE(l)))); SetOrg(Clock(PrevE(l)), OrgV(l)); /* Subdivision of the Octahedron (in four tetrahedron) delimitate by the medial nodes */ ??? o1 = MakeTriangle(FALSE); ??? o2 = MakeTriangle(FALSE); ??? o3 = MakeTriangle(FALSE); ??? o4 = MakeTriangle(FALSE); { assert(i == PrevF(Clock(g[1]))); assert(i == Clock(NextF(g[1]))); assert(i == Clock(PrevE(NextF(g[2])))); assert(j == PrevF(NextE(g[0]))); assert(k == Clock(PrevF(PrevE(g[0])))); assert(k == Clock(PrevE(PrevF(g[3])))); assert(l == Clock(PrevF(g[0]))); /* triangle o1 */ SetNextF(o1, NextE(k)); SetNextF(PrevE(g[1]), o1); SetNextF(PrevE(o1), NextE(g[0])); SetNextF(j, PrevE(o1)); /* Update the component @{edge->?} */ SetRingEdgeInfo(o1, PEdge(NextE(k))); SetRingEdgeInfo(PrevE(o1), PEdge(j)); /* Update the origins */ SetOrg(o1, OrgV(PrevE(g[1]))); SetOrg(Clock(o1), OrgV(Clock(PrevE(g[1])))); SetOrg(PrevE(o1), OrgV(NextE(g[0]))); SetOrg(Clock(PrevE(o1)), OrgV(Clock(NextE(g[0])))); SetOrg(NextE(o1), OrgV(PrevE(k))); SetOrg(Clock(NextE(o1)), OrgV(j)); /* triangle o2 */ SetNextF(NextE(o2), NextE(g[3])); SetNextF(NextE(i), NextE(o2)); SetNextF(PrevE(o2), PrevE(l)); SetNextF(NextE(g[2]), PrevE(o2)); /* Update the component @{edge->?} */ SetRingEdgeInfo(NextE(o2), PEdge(NextE(g[3]))); SetRingEdgeInfo(PrevE(o2), PEdge(NextE(g[2]))); /* Update the origins */ SetOrg(o2, OrgV(j)); SetOrg(Clock(o2), OrgV(PrevE(k))); SetOrg(NextE(o2), OrgV(NextE(g[3]))); SetOrg(Clock(NextE(o2)), OrgV(Clock(NextE(g[3])))); SetOrg(PrevE(o2), OrgV(NextE(g[2]))); SetOrg(Clock(PrevE(o2)), OrgV(Clock(NextE(g[2])))); /* triangle o3 */ SetNextF(o3, l); SetNextF(Clock(g[0]), o3); SetNextF(NextE(o3), g[3]); SetNextF(Clock(PrevE(k)), NextE(o3)); /* Update the component @{edge->?} */ SetRingEdgeInfo(o3, PEdge(l)); SetRingEdgeInfo(NextE(o3), PEdge(g[3])); /* Update the origins */ SetOrg(o3, OrgV(Clock(g[0]))); SetOrg(Clock(o3), OrgV(g[0])); SetOrg(NextE(o3), OrgV(g[3])); SetOrg(Clock(NextE(o3)), OrgV(Clock(g[3]))); SetOrg(PrevE(o3), OrgV(PrevE(k))); SetOrg(Clock(PrevE(o3)), OrgV(j)); /* triangle o4 */ SetNextF(g[1], NextE(o4)); SetNextF(NextE(o4), Clock(i)); SetNextF(PrevE(j), PrevE(o4)); SetNextF(PrevE(o4), Clock(PrevE(g[2]))); SetNextF(o4, o2); SetNextF(o2, Clock(PrevE(o3))); SetNextF(Clock(PrevE(o3)), Clock(NextE(o1))); /* Update the component @{edge->?} */ SetRingEdgeInfo(NextE(o4), PEdge(Clock(i))); SetRingEdgeInfo(PrevE(o4), PEdge(PrevE(j))); SetRingEdgeInfo(o2, PEdge(o2)); /* Update the origins */ SetOrg(NextE(o4), OrgV(g[1])); SetOrg(Clock(NextE(o4)), OrgV(Clock(g[1]))); SetOrg(PrevE(o4), OrgV(Clock(PrevE(g[2])))); SetOrg(Clock(PrevE(o4)), OrgV(PrevE(g[2]))); SetOrg(o4, OrgV(o2)); SetOrg(Clock(o4), OrgV(Clock(o2))); /* making eigth tetrahedral cells */ SetPnegOfNearbyWalls(j); SetPnegOfNearbyWalls(Clock(PrevF(PrevE(NextF(k))))); SetPnegOfNearbyWalls(Clock(PrevF(NextE(i)))); SetPnegOfNearbyWalls(Clock(PrevF(NextE(NextF(l))))); SetPnegOfNearbyWalls(PrevE(NextF(o1))); SetPnegOfNearbyWalls(o2); SetPnegOfNearbyWalls(NextF(o3)); SetPnegOfNearbyWalls(o4); if (o->assert){ /* Some strong assertions */ assert(Org(Srot(j)) == Pneg(j)); assert(Org(Srot(Clock(PrevF(PrevE(NextF(k)))))) == Pneg(Clock(PrevF(PrevE(NextF(k)))))); assert(Org(Srot(Clock(PrevF(NextE(i))))) == Pneg(Clock(PrevF(NextE(i))))); assert(Org(Srot(Clock(PrevF(NextE(NextF(l)))))) == Pneg(Clock(PrevF(NextE(NextF(l)))))); assert(Org(Srot(NextF(o3))) == Pneg(NextF(o3))); assert(Org(Srot(PrevE(NextF(o1)))) == Pneg(PrevE(NextF(o1)))); assert(Org(Srot(o4)) == Pneg(o4)); assert(Org(Srot(o2)) == Pneg(o2)); Place_t v = Srot(j); Place_t v1 = Clock(PrevE(Srot(j))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(NextF(o3)); Place_t v1 = Clock(PrevE(Srot(NextF(o3)))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(o2); Place_t v1 = Clock(PrevE(Srot(o2))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(o4); Place_t v1 = Clock(PrevE(Srot(o4))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(PrevE(NextF(o1))); Place_t v1 = Clock(PrevE(Srot(PrevE(NextF(o1))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(PrevE(NextF(k))))); Place_t v1 = Clock(PrevE(Srot(Clock(PrevF(PrevE(NextF(k))))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(NextE(i)))); Place_t v1 = Clock(PrevE(Srot(Clock(PrevF(NextE(i)))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(NextE(NextF(l))))); Place_t v1 = Clock(PrevE(Srot(Clock(PrevF(NextE(NextF(l))))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } } /* Now, refine the subdivision of the octahedron in more four tetrahedra, through the subdivision of the diagonal @{edge->?} of the octahedron. */ Subdivide@{Edge->?}(o2,in,o->net); } } } RefineCell; bool_t CreateNode(Place_t @p) Place_t t = a; VAR { ??? fe = NARROW(PWedge(a)-> Wedge_t); { ){ if (! fe.mark) { fe.mark = TRUE; do { ??? fe = NARROW(PWedge(t), Wedge_t); { ){ fe.mark = TRUE; } t = NextF(t) } while (t != a); return TRUE; } return FALSE; } } CreateNode; void SetAllVh(Place_t @p, Node_t v) /* Set all adjacents @places to "a" with the same medial node "v" */ void SetVh(b: Place_t) /* Set the @place "b" with the medial node "v". */ { ??? fe = NARROW(PWedge(b)-> Wedge_t); { ){ fe.vh = v; } } SetVh; Place_t t = a; VAR { do { SetVh(t); t = NextF(t); } while (t != a); } SetAllVh; void SetPnegOfNearbyWalls(Place_t @p) /* set the (12) places belonging to same 3-cell */ Place_t t = a; VAR { Cell_t p = MakeCell(); { SetPnegOfWall(t,p); do { SetPnegOfWall(Clock(PrevF(t)),p); t = PrevE(t); } while (t != a); } } SetPnegOfNearbyWalls; uint Vhnum(Place_t @p) /* given the @place "a", this procedure return the number of its medial node "vh". */ { ??? fe = NARROW(PWedge(a)-> Wedge_t); { ){ return fe.vh->num; } } Vhnum; { /* Copy the original nodes, save icorrespondence in "vnew" array: */ for (iu = 0; iu < top->node.ne; iu++) { ??? u = top->node[iu]; Node_t v = MakeNode(); { v->num = u->num; v->exists = u->exists; v.fixed = u.fixed) || (o->fixOri; v.color = u.color; v.radius = u.radius; v.label = u.label; vnew[iu] = v } } /* Create two new wedges for each original wedge "fe". The new wedge corresponding to the origin half of "fe", with same spin and orientation, will be | Half(a) == Spin^s(half[2*PWedge(a)->num + o]) where s == SpinBit(a), o == OrientationBit(a) */ REF Node_vec_t ve = Node_vec_new(top->NE); uint i = 0; { for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? ho = half[2*ie + oa]; ??? hd = half[2*ie + 1 - oa]; ??? fe = NARROW(PWedge(a)-> Wedge_t); { double fn = fe.wall->num; double en = fe.edge->num ){ if (( CreateNode(a))) { ve[i] = MakeNode(); ve[i]->num = top->node.ne + NNV; NNV++; ve[i]->exists = top->edge[en]->exists; ve[i].fixed = FALSE; ve[i].color = top->edge[en].color; ve[i].transp = top->edge[en].transp; ve[i].radius = top->edge[en].radius; ve[i].label = "VE"; SetAllVh(a, ve[i]); i++; } ho = MakeWedge(); ??? hoe = NARROW(PWedge(ho)-> Wedge_t); { ){ hoe.edge->exists = top->edge[en]->exists; hoe.edge.color = top->edge[en].color; hoe.edge.transp = top->edge[en].transp; hoe.edge.radius = top->edge[en].radius; /* set the "root" @{edge->?} */ hoe.edge->root = top->edge[en]->root; hoe.wall->exists = top->wall[fn]->exists; hoe.wall.color = top->wall[fn].color; hoe.wall.transp = top->wall[fn].transp; } if (sa == 1){ ho = Spin(ho); } hd = MakeWedge(); ??? hde = NARROW(PWedge(hd)-> Wedge_t); { ){ hde.edge->exists = top->edge[en]->exists; hde.edge.color = top->edge[en].color; hde.edge.transp = top->edge[en].transp; hde.edge.radius = top->edge[en].radius; /* set the "root" @{edge->?} */ hde.edge->root = top->edge[en]->root; hde.wall->exists = top->wall[fn]->exists; hde.wall.color = top->wall[fn].color; hde.wall.transp = top->wall[fn].transp; } if (sa == 1){ hd = Spin(hd); } SpliceEdges(ho, Clock(hd)); ??? m = Vhnum(a); { SetOrg(Clock(ho),ve[m-top->node.ne]); SetOrg(Clock(hd),ve[m-top->node.ne]); } SetOrg(ho, vnew[OrgV(a)->num]); SetOrg(hd, vnew[OrgV(Clock(a))->num]); } } } /* Connect the half-wedges as in the original triangulation */ for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((c!=a) && (NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } Place_t a = Clock(top->wedge[ie]); Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } } for (j = 0; j < top->wall.ne; j++) { Place_t *d,e,f,g; { ??? fa = top->wall[j]; ??? fr = fa->root; ??? a = fa.pa; Place_t b = NextE(a); Place_t c = PrevE(a); ??? ha = Half(a); with (hac == Half(Clock(a)), double hb = Half(b), hbc == Half(Clock(b)); double hc = Half(c), hcc == Half(Clock(c)) ){ d = MakeWedge(); PEdge(d)->exists = Thin@{Edge->?}Exists; e = MakeWedge(); PEdge(e)->exists = Thin@{Edge->?}Exists; f = MakeWedge(); PEdge(f)->exists = Thin@{Edge->?}Exists; if ((fa->exists) && (o->net)) { with ( double co = (frgb_t){1.00,1.00,0.50}, /* color and radius for the thin */ double ra = 0.0025, /* @{edge->?} on the net */ double de = PEdge(d); double ee = PEdge(e); double fe = PEdge(f) ){ de->exists = TRUE; ee->exists = TRUE; fe->exists = TRUE; de.color = co; de.radius = ra; ee.color = co; ee.radius = ra; fe.color = co; fe.radius = ra; } } /* Make the first link wedge */ SetNextE(hc, d); SetNextE(d, Clock(hbc)); SetNextE(Clock(hc), hbc); /* Update the origins */ SetOrg(d, OrgV(Clock(hc))); SetOrg(Clock(d), OrgV(Clock(hbc))); /* Update the component wall */ SetWallInfo(hc, PWall(d)); SetWallInfo(hbc, PWall(d)); PWall(d)->exists = top->wall[j]->exists; PWall(d).color = top->wall[j].color; PWall(d).transp = top->wall[j].transp; /* Make the second link wedge */ SetNextE(ha, e); SetNextE(e, Clock(hcc)); SetNextE(Clock(ha), hcc); /* Update the origins */ SetOrg(e, OrgV(Clock(ha))); SetOrg(Clock(e), OrgV(Clock(hcc))); /* Update the component wall */ SetWallInfo(ha, PWall(e)); SetWallInfo(hcc, PWall(e)); PWall(e)->exists = top->wall[j]->exists; PWall(e).color = top->wall[j].color; PWall(e).transp = top->wall[j].transp; /* Make the third link wedge */ SetNextE(hac, f); SetNextE(f, Clock(hb)); SetNextE(Clock(hac), hb); /* Update the origins */ SetOrg(f, OrgV(Clock(hac))); SetOrg(Clock(f), OrgV(Clock(hb))); /* Update the component wall */ SetWallInfo(hac, PWall(f)); SetWallInfo(hb, PWall(f)); PWall(f)->exists = top->wall[j]->exists; PWall(f).color = top->wall[j].color; PWall(f).transp = top->wall[j].transp; /* Create Triangular wall to insert */ if (top->wall[j]->exists ){ g = MakeTriangle(TRUE); } else { g = MakeTriangle(FALSE); } /* making the connections */ SetNextF(NextE(hc), Clock(g)); SetNextF(NextE(hbc), g); SetNextF(NextE(g), NextE(hcc)); SetNextF(Clock(NextE(g)), Clock(NextE(hcc))); SetNextF(Clock(NextE(hb)), PrevE(g)); SetNextF(Clock(NextE(hac)),Clock(PrevE(g))); /* Update the edge component */ SetRingEdgeInfo(g ,PEdge(d)); SetRingEdgeInfo(NextE(g) ,PEdge(e)); SetRingEdgeInfo(PrevE(g) ,PEdge(f)); /* Update the origins */ SetOrg(g, OrgV(Clock(d))); SetOrg(Clock(g), OrgV(d)); SetOrg(NextE(g), OrgV(Clock(e))); SetOrg(Clock(NextE(g)), OrgV(e)); SetOrg(PrevE(g), OrgV(f)); SetOrg(Clock(PrevE(g)), OrgV(Clock(f))); PWall(g).color = top->wall[j].color; PWall(g).transp = top->wall[j].transp; /* set the "root" wall */ PWall(d)->root = fr; PWall(e)->root = fr; PWall(f)->root = fr; PWall(g)->root = fr; /* end of the setting */ } } } for (i = 0; i < top->wall.nelE; i++) { ??? a = top->wedge[i]; ??? ha = Half(a); ??? hac = Half(Clock(a)); { SetRingEdgeInfo(ha, PEdge(ha)); SetRingEdgeInfo(hac, PEdge(hac)); } }; for (i = 0; i < top->cell.ne; i++) { ??? v = Srot(top.cell[i]); Place_t a = Tors(v); Place_t af = PrevF(a); Place_t ae = PrevE(a); Place_t aee = NextE(a); { assert(Pneg(a)->num == i); assert(Org(v)->num == i); if ((Ppos(af)!=NULL)){ assert(Pneg(a) == Ppos (af)); } gi[i,0] = Clock(NextE(PrevF(NextE(Half(a))))); gi[i,1] = Clock(NextE(NextF(NextE(Half(af))))); gi[i,2] = Clock(NextE(NextF(NextE(Half(PrevF(ae)))))); gi[i,3] = NextF(NextE(Half(PrevF(aee)))); } } for (i = 0; i < top->cell.ne; i++) { RefineCell(RowT{gi[i,0],gi[i,1],gi[i,2],gi[i,3]},i); } ntop = MakeElemTable(Half(top->wedge[1])); ??? nc = NEW(REF Coords_t; with (ntop.node.ne)^, double com = "Refined from: " & o->inFileTp & ".tp\n" & "Created by RefineTriang: " & o->outFile & ".tp" ){ assert(ntop.node.ne == top->node.ne + top->NE + top->cell.ne); assert(ntop.edge.ne == 2*top->NE + 3*top->wall.ne + 6*top->cell.ne); assert(ntop.wall.ne == 4*top->wall.ne + 16*top->cell.ne); assert(ntop.cell.ne == 12*top->cell.ne); /*if (top->bdr == 0){ assert(ntop.wedge.ne == 72*top->cell.ne); }*/ for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Half(a))->num; Node_t nv = OrgV(Half(Clock(a)))->num; Node_t nx = OrgV(Clock(Half(a)))->num; Node_t ny = OrgV(Clock(Half(Clock(a))))->num; { assert(nx == ny); nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); } } if (o->net) { /* we compute the number of existing walls in the previus topology. */ VAR nefp: uint = 0; /* existing walls in the previus topology*/ neep: uint = 0; /* existing @{edge->?}s in the previus topology*/ neea: uint = 0; /* existing @{edge->?}s in the actual topology*/ { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists){ nefp++;} } } for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { if (e->exists){ neep++; } } } for (i = 0; i < ntop.edge.ne; i++) { ??? e = ntop.edge[i]; { if (e->exists){ neea++;} } } assert(neea == 3 * nefp + 2 * neep); } } for (i = 0; i < top->cell.ne; i++) { Node_t ou = OrgV(gi[i; with (1])->num, double ov = OrgV(PrevE(gi[i,2]))->num ){ nc[x[i]->num] = r4_Scale(0.5, r4_Add(nc[ou], nc[ov])); } } WriteTopology (o->outFile, ntop, com); /*WriteTable (o->outFile, ntop, com);*/ WriteState (o->outFile, ntop, nc, com); WriteMaterials(o->outFile, ntop, com, FALSE); /* Now, unmark the attribute "mark" of Wedge_t */ for (i = 0; i < top->wall.nelE; i++) { ??? fe = NARROW(PWedge(top->wedge[i]), Wedge_t); { ){ if (fe.mark){ fe.mark = FALSE; } } } } } return 0; } PROCEDURE Subdivide@{Edge->?}(an : Place_t; i: INTEGER; bool_t net) == VAR a,bn,m1,m2,m3,t0,t1,Place_vec_t t2; wn, p: REF ARRAY OF @{Node->?}; CONST double n = 4; { a = NEW(REF Place_vec_t,n); bn = NEW(REF Place_vec_t,n); m1 = NEW(REF Place_vec_t,n); m2 = NEW(REF Place_vec_t,n); m3 = NEW(REF Place_vec_t,n); t0 = NEW(REF Place_vec_t,n); t1 = NEW(REF Place_vec_t,n); t2 = NEW(REF Place_vec_t,n); /* save the @places */ a = NEW(REF Place_vec_t,n); a[0] = an; for (i = 1; i < n; i++) { a[i] = NextF(a[i-1]); } /* save the nodes */ wn = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { wn[i] = Org(PrevE(a[i])); } /* save the cells */ p = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { p[i] = Pneg(a[i]); } /* save other @places */ bn = NEW(REF Place_vec_t,n); for (i = 0; i < n; i++) { bn[i] = Clock(PrevE(NextF(PrevE(a[i])))); } /* insert wedges and edges */ for (i = 0; i < n; i++) { m1[i] = MakeWedge(); m2[i] = MakeWedge(); m3[i] = MakeWedge(); t0[i] = MakeTriangle(FALSE); t1[i] = NextE(t0[i]); t2[i] = NextE(t1[i]); /* If net==TRUE the simulates the net with cylinders ans spheres, */ if ((net) && (PEdge(bn[i])->exists)) { PEdge(t0[i])->exists = TRUE; PEdge(t0[i]).radius = 0.0025; PEdge(t0[i]).color = (frgb_t){1.0,1.0,0.5}; } ??? f = PWedge(t0[i]).wall; ??? e1 = PEdge(t1[i]); ??? e2 = PEdge(t2[i]); { f->exists = FALSE; e1->exists = FALSE; e2->exists = FALSE; } } /* Now subdivide @{edge->?} and extend the subdivision on the star of the edge */ x[i] = MakeNode(); ??? v = NARROW(x[i], Node); { ){ v->exists = FALSE; v.label = "VE"; } for (j = 0; j < n; j++) { ??? ee = PEdge(a[j]); ??? ff = PEdge(m2[j]); Place_t b = NextE(a[j]); Edge_t be = PEdge(b); Place_t c = NextE(b); Edge_t ce = PEdge(c); ??? u = Org(a[j]); ??? v = Org(b); ??? w = Org(c); with ( /* save the attributes of the edge-wall component of the @place a[j] */ f == PWedge(a[j]).wall, g == PWedge(m3[j]).wall, double ge = g->exists; h == PEdge(m3[j]) ){ ee->exists = FALSE; ff->exists = FALSE; SetNextE(a[j],m1[j]); SetNextE(m1[j],c); SetNextE(m2[j],m3[j]); SetNextE(m3[j],Clock(b)); SetOrg(a[j], u); SetOrg(Clock(a[j]), x[i]); SetOrg(m2[j],v); SetOrg(Clock(m2[j]), x[i]); SetOrg(m3[j], x[i]); SetOrg(Clock(m3[j]), w); SetOrg(m1[j], x[i]); SetOrg(Clock(m1[j]), w); SetNextF(m1[j],m3[j]); /* set the attributes for the wall component */ ge = FALSE; SetRingWallInfo(a[j],f); SetRingWallInfo(m3[j],g); SetRingEdgeInfo(m3[j],h); SetRingEdgeInfo(b,be); SetRingEdgeInfo(c,ce); SetRingEdgeInfo(a[j],ee); SetRingEdgeInfo(m2[j],ff); SetRingWallInfo(bn[j],PWedge(bn[j]).wall); SetRingWallInfo(PrevF(bn[j]),PWedge(PrevF(bn[j])).wall); } } for (j = 0; j < n; j++) { SetNextF(Clock(m2[j]),Clock(m2[(j+1) % n])); } ??? ff = PEdge(m2[0]); { SetRingEdgeInfo(m2[0],ff); } for (j = 0; j < n; j++) { Place_t cn = NextF(bn[j]); ??? e0 = PEdge(t0[j]); ??? e1 = PEdge(t1[j]); ??? e2 = PEdge(t2[j]); { SetOrgAll(t0[j],wn[j]); SetOrgAll(t1[j],wn[(j+1) % n]); SetOrgAll(t2[j],x[i]); SetNextF(bn[j], t0[j]); SetNextF(t0[j],cn); SetNextF(m1[j],t2[j]); SetNextF(t2[j],m3[j]); SetNextF(Clock(m1[(j+1) % n]), t1[j]); SetNextF(t1[j],Clock(m3[(j+1) % n])); SetRingEdgeInfo(t0[j],e0); SetRingEdgeInfo(t1[j],e1); SetRingEdgeInfo(t2[j],e2); SetRingEdgeInfo(NextE(t0[j]),PEdge(NextE(t0[j]))); SetRingEdgeInfo(NextE(t1[j]),PEdge(NextE(t1[j]))); SetRingEdgeInfo(NextE(t2[j]),PEdge(NextE(t2[j]))); } } /* insert cells */ for (j = 0; j < n; j++) { ??? q = Triangulation.MakeCell(); { Triangulation.SetPnegOfNearbyWalls(a[j],p[j]); Triangulation.SetPnegOfNearbyWalls(m2[j],q); } } } /* END Subdivide@{Edge->?} */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->fixOri = argparser_keyword_present(pp, "-fixOri"); o->net = argparser_keyword_present(pp, "-net"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: RefineTriang \\\n"); fprintf(stderr, " -inFileTp \\\n"); fprintf(stderr, " -inFileSt \\\n"); fprintf(stderr, " -outFile \\\n"); fprintf(stderr, " [ -fixOri ] [-assert] [-net]\n"); END¦ } } return o; } GetOptions; Place_t MakeTriangle(bool_t exists) /* Make one triangular wall and set of the three places with the same wall component. If exists is TRUE then the triangular wall exists, FALSE otherwise. */ { Place_t a = MakeWedge(); Place_t b = MakeWedge(); Place_t c = MakeWedge(); Wall_t f = PWall(a); Node_t u = MakeNode(); Node_t v = MakeNode(); Node_t w = MakeNode(); { if (exists){ f->exists = TRUE }else{ f->exists = FALSE; } PEdge(a)->exists = Thin@{Edge->?}Exists; SetOrg(a, u); SetOrg(Clock(a),v); PEdge(b)->exists = Thin@{Edge->?}Exists; SetNextE(a,b); SetWallInfo (b,f); SetOrg (b,v); SetOrg(Clock(b),w); PEdge(c)->exists = Thin@{Edge->?}Exists; SetNextE(b,c); SetWallInfo (c,f); SetOrg (c, w); SetOrg(Clock(c), OrgV(a)); return a; } } /* END MakeTriangle */ { DoIt() } RefineTriang. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/RefineTriangGood.c #define PROG_NAME "RefineTriangGood" #define PROG_DESC "???" #define PROG_VERS "1.0" #define RefineTriangGood_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Refines (or duplicate) a given triangulation (".tp" file). (see notice of copyright at the end of this file). This program is inspired in the implementations of for the bidimensional case. */ #define RefineTriangGood_C_author \ "Created in 1999 by L. Lozada, basd on a 2D version by R. M. Rosi and J. Stolfi" #include // #INCLUDE // #INCLUDE #include #include TYPE typedef struct Options_t { char *inFileTp; /* Input file name (minus ".tp" extension) */ char *inFileSt; /* Input file name (minus ".st" extension) */ char *outFile; /* Output file name prefix */ bool_t fixOriginal; /* TRUE to fix original nodes */ } double RowT = ARRAY [0..3] OF Place_t; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) CONST double Thin@{Edge->?}Radius = 0.0025; uint NNE = 0; NNV: uint = 0; NNP: uint = 0; gi : REF ARRAY OF Place_vec_t; n{ ElemTableRec_t top; Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToTaMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? c = rc^; ??? half = Place_vec_new(2*top->wall.nelE)^; ??? vnew = Node_vec_new(top->node.ne)^; { if (top->der!=3) { fprintf(stderr,"This topology isn't a triangulation\n"); Process.Exit¦(1); } fprintf(stderr, "Refining from: " & o->inFileTp & ".tp\n"); gi = NEW(REF ARRAY OF Place_vec_t, top->cell.ne, 4); Place_t Half(Place_t @p) { ??? na = PWedge(a)->num; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? h = half[2*na + oa]; { if (sa == 0){ return h }else{ return Spin(h); } } } Half; Place_t MakeTriangle(void) /* Make one triangular wall and set of the three places with the same wall component. */ { Place_t a = MakeWedge(); Place_t b = MakeWedge(); Place_t c = MakeWedge(); Wall_t f = PWall(a); Node_t u = MakeNode(); Node_t v = MakeNode(); Node_t w = MakeNode(); { PWedge(a)->num = NNE; NNE++; PWedge(a)->num = NNE; NNE++; PEdge(a).radius = Thin@{Edge->?}Radius; SetOrg(a, u); SetOrg(Clock(a),v); PWedge(b)->num = NNE; NNE++; PEdge(b).radius = Thin@{Edge->?}Radius; SetNextE(a,b); SetWallInfo(b,f); SetOrg(b,v); SetOrg(Clock(b),w); PWedge(c)->num = NNE; NNE++; PEdge(c).radius = Thin@{Edge->?}Radius; SetNextE(b,c); SetWallInfo(c,f); SetOrg(c, w); SetOrg(Clock(c), OrgV(a)); return a; } } MakeTriangle; /* ====== Refine the Tetrahedral Cell ====== */ void RefineCell(g: RowT) { /* To insert four walls obliques "i", "j", "k", "l" */ ??? i = MakeTriangle(); with ( j == MakeTriangle(), double k = MakeTriangle(), l == MakeTriangle() ){ /* the wall "i" will be splice with g[1], g[2], g[3] */ SetNextF(i,Clock(g[1])); SetNextF(NextE(i),NextE(g[3])); SetNextF(PrevE(i),Clock(g[2])); /* Update the component @{edge->?} */ SetEdgeInfo(i, PEdge(g[1])); SetEdgeInfo(NextE(i), PEdge(NextE(g[3]))); SetEdgeInfo(PrevE(i), PEdge(g[2])); /* Update the origins */ SetOrg(i, OrgV(g[2])); SetOrg(Clock(i), OrgV(g[1])); SetOrg(NextE(i), OrgV(Clock(i))); SetOrg(Clock(NextE(i)), OrgV(NextE(g[2]))); SetOrg(PrevE(i), OrgV(Clock(NextE(i)))); SetOrg(Clock(PrevE(i)), OrgV(i)); /* the wall "j" will be splice with: g[0], g[1], g[2] */ SetNextF(j,NextE(g[0])); SetNextF(NextE(j),Clock(NextE(g[1]))); SetNextF(PrevE(j),Clock(PrevE(g[2]))); /* Update the component @{edge->?} */ SetEdgeInfo(j, PEdge(NextE(g[0]))); SetEdgeInfo(NextE(j), PEdge(NextE(g[1]))); SetEdgeInfo(PrevE(j), PEdge(PrevE(g[2]))); /* Update the origins */ SetOrg(j, OrgV(NextE(g[0]))); SetOrg(Clock(j), OrgV(PrevE(g[0]))); SetOrg(NextE(j), OrgV(Clock(j))); SetOrg(Clock(NextE(j)), OrgV(g[2])); SetOrg(PrevE(j), OrgV(Clock(NextE(j)))); SetOrg(Clock(PrevE(j)), OrgV(j)); /* the wall "k" will be splice with: g[0], g[1], g[3]) */ SetNextF(k,Clock(PrevF(PrevE(g[0])))); SetNextF(NextE(k),NextF(PrevE(g[1]))); SetNextF(PrevE(k),Clock(PrevF(g[3]))); /* Update the component @{edge->?} */ SetEdgeInfo(k,PEdge(PrevE(g[0]))); SetEdgeInfo(NextE(k),PEdge(PrevE(g[1]))); SetEdgeInfo(PrevE(k),PEdge(g[3])); /* Update the origins */ SetOrg(k, OrgV(g[0])); SetOrg(Clock(k), OrgV(PrevE(g[0]))); SetOrg(NextE(k), OrgV(Clock(k))); SetOrg(Clock(NextE(k)), OrgV(g[1])); SetOrg(PrevE(k), OrgV(Clock(NextE(k)))); SetOrg(Clock(PrevE(k)), OrgV(k)); /* the wall "l" will be splice with: g[0], g[2], g[3] */ SetNextF(l, Clock(PrevF(g[0]))); SetNextF(NextE(l), Clock(PrevF(PrevE(g[3])))); SetNextF(PrevE(l), NextF(NextE(g[2]))); /* Update the component @{edge->?} */ SetEdgeInfo(l, PEdge(g[0])); SetEdgeInfo(NextE(l), PEdge(PrevE(g[3]))); SetEdgeInfo(PrevE(l), PEdge(NextE(g[2]))); /* Update the origins */ SetOrg(l, OrgV(Clock(g[0]))); SetOrg(Clock(l), OrgV(g[0])); SetOrg(NextE(l), OrgV(Clock(l))); SetOrg(Clock(NextE(l)), OrgV(NextE(g[2]))); SetOrg(PrevE(l), OrgV(Clock(NextE(l)))); SetOrg(Clock(PrevE(l)), OrgV(l)); /* Subdivision of Octahedron delimitate by nodes mediates */ ??? o1 = MakeTriangle(); with ( o2 == MakeTriangle(), double o3 = MakeTriangle(), o4 == MakeTriangle() ){ assert(i == PrevF(Clock(g[1]))); assert(i == Clock(NextF(g[1]))); assert(i == Clock(PrevE(NextF(g[2])))); assert(j == PrevF(NextE(g[0]))); assert(k == Clock(PrevF(PrevE(g[0])))); assert(k == Clock(PrevE(PrevF(g[3])))); assert(l == Clock(PrevF(g[0]))); /* triangle o1 */ SetNextF(o1, NextE(k)); SetNextF(PrevE(g[1]), o1); SetNextF(PrevE(o1), NextE(g[0])); SetNextF(j, PrevE(o1)); /* Update the component @{edge->?} */ SetEdgeInfo(o1, PEdge(NextE(k))); SetEdgeInfo(PrevE(o1), PEdge(j)); /* Update the origins */ SetOrg(o1, OrgV(PrevE(g[1]))); SetOrg(Clock(o1), OrgV(Clock(PrevE(g[1])))); SetOrg(PrevE(o1), OrgV(NextE(g[0]))); SetOrg(Clock(PrevE(o1)), OrgV(Clock(NextE(g[0])))); SetOrg(NextE(o1), OrgV(PrevE(k))); SetOrg(Clock(NextE(o1)), OrgV(j)); /* triangle o2 */ SetNextF(NextE(o2), NextE(g[3])); SetNextF(NextE(i), NextE(o2)); SetNextF(PrevE(o2), PrevE(l)); SetNextF(NextE(g[2]), PrevE(o2)); /* Update the component @{edge->?} */ SetEdgeInfo(NextE(o2), PEdge(NextE(g[3]))); SetEdgeInfo(PrevE(o2), PEdge(NextE(g[2]))); /* Update the origins */ SetOrg(o2, OrgV(j)); SetOrg(Clock(o2), OrgV(PrevE(k))); SetOrg(NextE(o2), OrgV(NextE(g[3]))); SetOrg(Clock(NextE(o2)), OrgV(Clock(NextE(g[3])))); SetOrg(PrevE(o2), OrgV(NextE(g[2]))); SetOrg(Clock(PrevE(o2)), OrgV(Clock(NextE(g[2])))); /* triangle o3 */ SetNextF(o3, l); SetNextF(Clock(g[0]), o3); SetNextF(NextE(o3), g[3]); SetNextF(Clock(PrevE(k)), NextE(o3)); /* Update the component @{edge->?} */ SetEdgeInfo(o3, PEdge(l)); SetEdgeInfo(NextE(o3), PEdge(g[3])); /* Update the origins */ SetOrg(o3, OrgV(Clock(g[0]))); SetOrg(Clock(o3), OrgV(g[0])); SetOrg(NextE(o3), OrgV(g[3])); SetOrg(Clock(NextE(o3)), OrgV(Clock(g[3]))); SetOrg(PrevE(o3), OrgV(PrevE(k))); SetOrg(Clock(PrevE(o3)), OrgV(j)); /* triangle o4 */ SetNextF(g[1], NextE(o4)); SetNextF(NextE(o4), Clock(i)); SetNextF(PrevE(j), PrevE(o4)); SetNextF(PrevE(o4), Clock(PrevE(g[2]))); SetNextF(o4, o2); SetNextF(o2, Clock(PrevE(o3))); SetNextF(Clock(PrevE(o3)), Clock(NextE(o1))); /* Update the component @{edge->?} */ SetEdgeInfo(NextE(o4), PEdge(Clock(i))); SetEdgeInfo(PrevE(o4), PEdge(PrevE(j))); SetRingEdgeInfo(o2, PEdge(o2)); /* Update the origins */ SetOrg(NextE(o4), OrgV(g[1])); SetOrg(Clock(NextE(o4)), OrgV(Clock(g[1]))); SetOrg(PrevE(o4), OrgV(Clock(PrevE(g[2])))); SetOrg(Clock(PrevE(o4)), OrgV(PrevE(g[2]))); SetOrg(o4, OrgV(o2)); SetOrg(Clock(o4), OrgV(Clock(o2))); /* making eigth cell tetrahedral */ SetPnegOfNearbyWalls(j); SetPnegOfNearbyWalls(Clock(PrevF(PrevE(NextF(k))))); SetPnegOfNearbyWalls(Clock(PrevF(NextE(i)))); SetPnegOfNearbyWalls(Clock(PrevF(NextE(NextF(l))))); SetPnegOfNearbyWalls(PrevE(NextF(o1))); SetPnegOfNearbyWalls(o2); SetPnegOfNearbyWalls(NextF(o3)); SetPnegOfNearbyWalls(o4); /* tests */ assert(Org(Srot(j)) == Pneg(j)); assert(Org(Srot(Clock(PrevF(PrevE(NextF(k)))))) == Pneg(Clock(PrevF(PrevE(NextF(k)))))); assert(Org(Srot(Clock(PrevF(NextE(i))))) == Pneg(Clock(PrevF(NextE(i))))); assert(Org(Srot(Clock(PrevF(NextE(NextF(l)))))) == Pneg(Clock(PrevF(NextE(NextF(l)))))); assert(Org(Srot(NextF(o3))) == Pneg(NextF(o3))); assert(Org(Srot(PrevE(NextF(o1)))) == Pneg(PrevE(NextF(o1)))); assert(Org(Srot(o4)) == Pneg(o4)); assert(Org(Srot(o2)) == Pneg(o2)); Place_t v = Srot(j), v1 == Clock(PrevE(Srot(j))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(NextF(o3)), v1 == Clock(PrevE(Srot(NextF(o3)))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(o2), v1 == Clock(PrevE(Srot(o2))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(o4), v1 == Clock(PrevE(Srot(o4))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(PrevE(NextF(o1))), double v1 = Clock(PrevE(Srot(PrevE(NextF(o1))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(PrevE(NextF(k))))), double v1 = Clock(PrevE(Srot(Clock(PrevF(PrevE(NextF(k))))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(NextE(i)))), double v1 = Clock(PrevE(Srot(Clock(PrevF(NextE(i)))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } Place_t v = Srot(Clock(PrevF(NextE(NextF(l))))), double v1 = Clock(PrevE(Srot(Clock(PrevF(NextE(NextF(l))))))); { assert(Pneg(Tors(v)) == Pneg(Tors(v1))); } } } } RefineCell; bool_t CreateNode(Place_t @p) Place_t t = a; VAR { ??? fe = NARROW(PWedge(a)-> with (TriangulationWedge_t) ){ if (! fe.mark) { fe.mark = TRUE; do { ??? fe = NARROW(PWedge(t); with (TriangulationWedge_t) ){ fe.mark = TRUE; } t = NextF(t) } while (t != a); return TRUE; } return FALSE; } } CreateNode; void SetAllVhnum(Place_t @p, uint n) void SetVhnum(Place_t @p, n : uint) { ??? fe = NARROW(PWedge(a)-> TriangulationWedge_t); { fe.vhnum = n; } } SetVhnum; Place_t t = a; VAR { do { SetVhnum(t,n); t = NextF(t); } while (t != a); } SetAllVhnum; void SetPnegOfNearbyWalls(Place_t @p) /* set the @places walldeges belong to same cell */ Place_t t = a; VAR { Cell_t p = MakeCell(); { p->num = NNP; NNP++; SetPnegOfWall(t,p); do { SetPnegOfWall(Clock(PrevF(t)),p); t = PrevE(t); } while (t != a); } } SetPnegOfNearbyWalls; uint Vhnum(Place_t @p) { ??? fe = NARROW(PWedge(a)-> TriangulationWedge_t); { return fe.vhnum; } } Vhnum; { /* Copy original nodes, save correspondence in "vnew" array: */ for (iu = 0; iu < top->node.ne; iu++) { ??? u = top->node[iu]; Node_t v = MakeNode(); { v->num = u->num; v->exists = u->exists; v.fixed = u.fixed) || (o->fixOriginal; v.color = u.color; v.radius = u.radius; vnew[iu] = v } } /* Create two new wedges for each original wedge "fe". The new wedge corresponding to the origin half of "fe", with same spin and orientation, will be | Half(a) == Spin^s(half[2*PWedge(a)->num + s]) where s == SpinBit(a), s == OrientationBit(a) */ REF Node_vec_t ve = Node_vec_new(top->NE); uint i = 0; { for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; ??? oa = OrientationBit(a); ??? sa = SpinBit(a); ??? ho = half[2*ie + oa]; ??? hd = half[2*ie + 1 - oa]; ??? fe = NARROW(PWedge(a)-> with ( TriangulationWedge_t), double b = CreateNode(a) ){ if (b) { ve[i] = MakeNode(); ve[i]->num = top->node.ne + NNV; INC (NNV); ve[i]->exists = top->edge[fe.edge->num]->exists; ve[i].fixed = FALSE; ve[i].radius = fe.edge.radius; ve[i].color = fe.edge.color; SetAllVhnum(a, ve[i]->num); i++; } ho = MakeWedge(); ??? hoe = NARROW(PWedge(ho)-> TriangulationWedge_t); { hoe->num = NNE; NNE++; hoe.edge->exists = fe.edge->exists; hoe.edge.radius = fe.edge.radius; hoe.edge.color = fe.edge.color; } if (sa == 1){ ho = Spin(ho); } hd = MakeWedge(); ??? hde = NARROW(PWedge(hd)-> TriangulationWedge_t); { hde->num = NNE; NNE++; hde.edge->exists = fe.edge->exists; hde.edge.radius = fe.edge.radius; hde.edge.color = fe.edge.color; } if (sa == 1){ ho = Spin(ho); } SpliceEdges(ho, Clock(hd)); ??? m = Vhnum(a); { SetOrg(Clock(ho),ve[m-top->node.ne]); SetOrg(Clock(hd),ve[m-top->node.ne]); } SetOrg(ho, vnew[OrgV(a)->num]); SetOrg(hd, vnew[OrgV(Clock(a))->num]); } } } /* Connect the half-wedges as in the original triangulation */ for (ie = 0; ie < top->wall.nelE; ie++) { ??? a = top->wedge[ie]; Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((c!=a) && (NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } Place_t a = Clock(top->wedge[ie]); Place_t b = NextF(a); Place_t c = NextE(a); ??? ha = Half(a); ??? hac = Half(Clock(a)); ??? hb = Half(b); ??? hc = Half(c); { if ((b!=a) && (NextF(ha)!=hb)) { SetNextF(ha, hb); /* so, NextF(ha) == hb */ SetEdgeInfo(hb, PEdge(ha)); } if ((NextE(Clock(hac))!=hc)) { SetNextE(Clock(hac), hc); /* so, NextE(Clock(hac) == hc */ } } } for (j = 0; j < top->wall.ne; j++) { Place_t *d,e,f,g; { ??? a = top->wall[j].pa^; with ( b == NextE(a), c == PrevE(a), double ha = Half(a), hac == Half(Clock(a)); double hb = Half(b), hbc == Half(Clock(b)); double hc = Half(c), hcc == Half(Clock(c)) ){ d = MakeWedge(); PWedge(d)->num = NNE; NNE++; PEdge(d).radius = Thin@{Edge->?}Radius; e = MakeWedge(); PWedge(e)->num = NNE; NNE++; PEdge(e).radius = Thin@{Edge->?}Radius; f = MakeWedge(); PWedge(f)->num = NNE; NNE++; PEdge(f).radius = Thin@{Edge->?}Radius; /* first wedge link */ SetNextE(hc, d); SetNextE(d, Clock(hbc)); SetNextE(Clock(hc), hbc); /* Update the Origins */ SetOrg(d, OrgV(Clock(hc))); SetOrg(Clock(d), OrgV(Clock(hbc))); /* Update the component wall */ SetWallInfo(hc, PWall(d)); SetWallInfo(hbc, PWall(d)); PWall(d).color = top->wall[j].color; PWall(d).transp = top->wall[j].transp; /* second wedge link*/ SetNextE(ha, e); SetNextE(e, Clock(hcc)); SetNextE(Clock(ha), hcc); /* Update the Origins */ SetOrg(e, OrgV(Clock(ha))); SetOrg(Clock(e), OrgV(Clock(hcc))); /* Update the component wall */ SetWallInfo(ha, PWall(e)); SetWallInfo(hcc, PWall(e)); PWall(e).color = top->wall[j].color; PWall(e).transp = top->wall[j].transp; /* thrid wedge link */ SetNextE(hac, f); SetNextE(f, Clock(hb)); SetNextE(Clock(hac), hb); /* Update the Origins */ SetOrg(f, OrgV(Clock(hac))); SetOrg(Clock(f), OrgV(Clock(hb))); /* Update the component wall */ SetWallInfo(hac, PWall(f)); SetWallInfo(hb, PWall(f)); PWall(f).color = top->wall[j].color; PWall(f).transp = top->wall[j].transp; /* Create Triangular Wall to insert */ g = MakeTriangle(); /* making connections */ SetNextF(NextE(hc), Clock(g)); SetNextF(NextE(hbc), g); SetNextF(NextE(g), NextE(hcc)); SetNextF(Clock(NextE(g)), Clock(NextE(hcc))); SetNextF(Clock(NextE(hb)), PrevE(g)); SetNextF(Clock(NextE(hac)),Clock(PrevE(g))); /* Update the component @{edge->?} */ SetEdgeInfo(d, PEdge(Clock(g))); SetEdgeInfo(e, PEdge(Clock(NextE(g)))); SetEdgeInfo(f, PEdge(PrevE(g))); /* Update the Origins */ SetOrg(g, OrgV(Clock(d))); SetOrg(Clock(g), OrgV(d)); SetOrg(NextE(g), OrgV(Clock(e))); SetOrg(Clock(NextE(g)), OrgV(e)); SetOrg(PrevE(g), OrgV(f)); SetOrg(Clock(PrevE(g)), OrgV(Clock(f))); PWall(g).color = top->wall[j].color; PWall(g).transp = top->wall[j].transp; } } } for (i = 0; i < top->wall.nelE; i++) { ??? a = top->wedge[i]; ??? ha = Half(a); ??? hac = Half(Clock(a)); { SetRingEdgeInfo(ha, PEdge(ha)); SetRingEdgeInfo(hac, PEdge(hac)); } }; for (i = 0; i < top->cell.ne; i++) { ??? v = Srot(top.cell[i]), a == Tors(v), af == PrevF(a), double ae = PrevE(a), aee == NextE(a) ; { assert(Pneg(a)->num == i); assert(Org(v)->num == i); if ((Ppos(af)!=NULL)){ assert(Pneg(a) == Ppos (af)); } gi[i,0] = Clock(NextE(PrevF(NextE(Half(a))))); gi[i,1] = Clock(NextE(NextF(NextE(Half(af))))); gi[i,2] = Clock(NextE(NextF(NextE(Half(PrevF(ae)))))); gi[i,3] = NextF(NextE(Half(PrevF(aee)))); } } for (i = 0; i < top->cell.ne; i++) { RefineCell(RowT{gi[i,0],gi[i,1],gi[i,2],gi[i,3]}); } if (top->bdr == 0) { ntop = MakeElemTable(Half(top->wedge[1]),0); } else { ntop = MakeElemTable(Half(top->wedge[1]),1); } ??? nc = NEW(REF Coords_t; with ( ntop.node.ne)^, double cmt = "Refined from: " & o->inFileTp & ".tp\n" & "Created by RefineTriang: " & o->outFile & ".tp" ){ assert(ntop.node.ne == top->node.ne + top->NE); assert(ntop.edge.ne == 2*top->NE + 3*top->wall.ne + top->cell.ne); assert(ntop.wall.ne == 4*top->wall.ne + 8*top->cell.ne); assert(ntop.cell.ne == 8*top->cell.ne); if (top->bdr == 0){ assert(ntop.wedge.ne == 48*top->cell.ne); } for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Half(a))->num; Node_t nv = OrgV(Half(Clock(a)))->num; Node_t nx = OrgV(Clock(Half(a)))->num; Node_t ny = OrgV(Clock(Half(Clock(a))))->num; { assert(nx == ny); nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); } } WriteTopology(o->outFile, ntop, cmt); MakeElemTableTable(o->outFile, ntop, cmt); WriteState(o->outFile, ntop, nc, cmt); Triangulation.FindDegeneracies(ntop); WriteMaterials(o->outFile, ntop, cmt); /* Now, unmark the attribute "mark" of TriangulationWedge_t */ for (i = 0; i < top->wall.nelE; i++) { ??? fe = NARROW(PWedge(top->wedge[i]); with ( TriangulationWedge_t) ){ if (fe.mark){ fe.mark = FALSE; } } } } } return 0; } Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->fixOriginal = argparser_keyword_present(pp, "-fixOriginal"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: RefineTriang \\\n" \ " -inFileTp \\\n" \ " -inFileSt \\\n" \ " -outFile \\\n" \ " [ -fixOriginal ] \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } RefineTriangGood. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/RootBarycenter.c #define PROG_NAME "RootBarycenter" #define PROG_DESC "???" #define PROG_VERS "1.0" #define RootBarycenter_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program builds the "barycentric subdivision" of a topology (".tp" file) of a given 3D cellular map without boundary or with boundary. . Added the heredity of the "root" attributes for tetrahedra. */ #include // #INCLUDE #include // #INCLUDE #include #include // #INCLUDE // #INCLUDE #include // // #INCLUDE // Place_t, Org, MakeElemTable, PposP, PnegP, OrgV, Node, @{Edge->?}, Wall, Pneg, Ppos; // #INCLUDE // NextF, Srot, Clock, NextE, PrevF, PrevE, Spin, Tors; // #INCLUDE // Bary_Corner, CCorner, SetCorner; CONST double order = 2; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ bool_t fixed; /* Retains the previous geometry */ bool_t net; /* Implements the net walls */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) REF Place_vec_t ps ; nvv,nve,nvf,nvp: uint = 0; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile; with (TRUE), double top = tc.top; rc == Triangulation.ReadState(o->inFile), c == rc^, double NFE = top->wall.nelE; double vlt = "VP"; vlf == "VF" ){ Place_vec_t ps = Place_vec_new(NFE); fprintf(stderr, "Subdividing from: " & o->inFile & ".tp\n"); for (i = 0; i < NFE; i++) { ??? aposp = PposP(top->wedge[i]); with ( double apneg = PnegP(top->wedge[i]) DO if ((aposp != NULL) && (apneg #NULL)) { /* Make one Topological tetrahedron of 2x2 order, for each wedge in the topology and set the atributes "ca" for each original wedge. */ ps[i] = Bary.MakeWedge(order,order); ??? fes = NARROW(PWedge(ps[i]), Bary.wedge); with ( double fet = PWedge(top->wedge[i]); fn == fet.wall->num, en == fet.edge->num, on == OrgV(top->wedge[i]), dn == OrgV(Clock(top->wedge[i])), double ovr = on.radius; double ovc = on.color; double ovt = on.transp; double ovl = on.label; double ove = on->exists; double dvr = dn.radius; double dvc = dn.color; double dvt = dn.transp; double dvl = dn.label; double dve = dn->exists; double era = top->edge[en].radius; double eco = top->edge[en].color; double eta = top->edge[en].transp; double eex = top->edge[en]->exists; double ero = top->edge[en]->root; double fco = top->wall[fn].color; double fta = top->wall[fn].transp; double fex = top->wall[fn]->exists; double fro = top->wall[fn]->root ){ assert(Octf.OrientationBit(top->wedge[i]) == 0); fet.ca = fes.ca; SetTetraRoot(fet.ca.e[0],apneg->num,aposp->num,(frgb_t){1.0,1.0,1.0}); SetDual (fet.ca.e[3],vlt,vlf,FALSE,TRUE); SetPrimal(fet.ca.e[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,FALSE,TRUE,o->net); } } } } if ((! IsMapWithBorder(top))) { for (i = 0; i < NFE; i++) { ??? pa = top->wedge[i]; { GlueTetra(pa) } } ??? newtop = MakeElemTable(PWedge(top->wedge[NFE-1]).ca.e[1]); ??? nc = GenCoords(newtop)^; with ( double cmt = "Subdivided from: " & o->inFile & ".tp\n" &"Created by Barycenter Subdivision: "&o->outFile \ ".tp on " & Today() DO for (i = 0; i < newtop.node.ne; i++) { ??? v = NARROW(newtop.node[i]; with (Triangulation.Node), double vl = v.label ){ if (( Text.Equal(vl,"VV"))){ nvv++; } else if (0 == strcmp(vl,"VE"))){ nve++; } else if (0 == strcmp(vl,"VF"))){ nvf++; } else if (0 == strcmp(vl,"VP"))){ nvp++; } } } assert(newtop.node.ne == nvv + nve + nvf + nvp); assert(newtop.node.ne == top->node.ne + top->NE + top->wall.ne + top->cell.ne); assert(newtop.wall.ne == 8 * top->wall.nelE); assert(newtop.wedge.ne == 24 * top->wall.nelE); assert(newtop.cell.ne == 4 * top->wall.nelE); if (o->fixed) { /* compute new coordinates for nodes of type "VV" and "VE". */ for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Bary_Corner(a))->num; Node_t nv = OrgV(Bary_Corner(Clock(a)))->num; Node_t nx = OrgV(Clock(Bary_Corner(a)))->num; { nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); } } /* compute new coordinates for nodes of type "VF". */ for (j = 0; j < top->wall.ne; j++) { ??? a = top->wall[j].pa; Node_t uu = OrgV(Clock(Bary_Corner(Srot(a)))); with (/* type VF */ double un = (Node_t)(uu); double ul = un.label ){ assert0 == strcmp(ul,"VF")); nc[un->num] = Triangulation.WallBarycenter(a,c); } } /* compute new coordinates for nodes of type "VP". */ for (j = 0; j < top->cell.ne; j++) { ??? a = Srot(top->cell[j]); ??? p = Triangulation.MakeCellTopology(a); Place_t b = Tors(a); Node_t uu = OrgV(Bary_Corner(Srot(b))); ??? un = (Node_t)(uu); with ( ){ r4_t ba = (r4_t){0.0,0.0,0.0,0.0}; VAR { for (k = 0; k < p.NV; k++) { ??? ver = p.vRef[k]; Node_t num = OrgV(ver)->num; { ba = r4_Add(ba,c[num]); } } nc[un->num] = r4_Scale(1.0/FLOAT(p.NV,double),ba); } } } } WriteTopology(o->outFile, newtop, cmt); WriteState(o->outFile, newtop, nc, cmt \ "\nRandom Geometry"); WriteMaterials(o->outFile, newtop, cmt, TRUE); /* unmark all the wedges */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); { fet.marks = FALSE; } } } } return 0; } PROCEDURE GlueTetra(Place_t @p) /* Glueing the topological tetrahedra such as the topology. */ { assert(PBits(a) == 0); Place_t b = NextF(a); Place_t c = PrevF(a); Place_t d = NextE(a); Place_t e = PrevE(a); { ??? aa = Bary_Corner(a); ??? bb = Bary_CCorner(b); { if (bb != aa) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(bb, aa, order,TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(a, bb); Bary_SetCorner(Spin(Clock(a)), Bary_CCorner(Spin(Clock(b)))); } } ??? cc = Bary_Corner(c); ??? dd = Bary_CCorner(a); { if (dd != cc) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(dd, cc, order,TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(c, dd); Bary_SetCorner(Spin(Clock(c)), Bary_CCorner(Spin(Clock(a)))); } } ??? ee = Bary_Corner(Srot(d)); ??? ff = Bary_CCorner(Srot(a)); { if (ff != ee) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(ff, ee, order,TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(d), ff); Bary_SetCorner(Spin(Tors(d)), Bary_CCorner(Spin(Tors(a)))); } } ??? gg = Bary_Corner(Srot(a)); ??? hh = Bary_CCorner(Srot(e)); { if (gg != hh) { EVAL Triangulation.Glue(hh, gg, order,TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(a), hh); Bary_SetCorner(Spin(Tors(a)), Bary_CCorner(Spin(Tors(e)))); } } } } /* END GlueTetra */ PROCEDURE SetTetraRoot( Place_t @p; /* @place of the tetrahedron 2x2 or 1x2 */ uint rn; /* root of the Pneg(a) */ uint rp; /* root of the Ppos(a) */ co: frgb_t; /* color of the Pneg(a) */ ) == void SetPnegOfNearbyWallsRoot(Place_t @p, ro: uint) /* Set the (12) places belonging to same tetrahedron with the same root attribute "ro". */ void SetPnegRoot(b: Place_t) /* Set the cell PnegP(b) with root equal to "ro". */ { with ( double p = Triangulation.PnegP(b) DO p->root = ro; p.color = co; } } SetPnegRoot; void SetPnegOfWallRoot(Place_t c) /* Repeat the SetPnegRoot procedure for each @place belonging to the same triangular wall. */ Place_t t = c; VAR { do { SetPnegRoot(t); t = PrevE(t); } while (t != c); } SetPnegOfWallRoot; Place_t t = a; VAR { SetPnegOfWallRoot(t); do { SetPnegOfWallRoot(Clock(PrevF(t))); t = PrevE(t); } while (t != a); } SetPnegOfNearbyWallsRoot; { SetPnegOfNearbyWallsRoot(a, rp); SetPnegOfNearbyWallsRoot(Clock(NextF(a)), rn); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetPnegOfNearbyWallsRoot(b, rp); SetPnegOfNearbyWallsRoot(Clock(NextF(b)), rn); } } /* END SetTetraRoot */ PROCEDURE SetPrimal(Place_t @p, /* @place of the topological tetrahedron 2x2 or 1x2 */ REAL ovr; /* origen node radius */ ovc: frgb_t; /* origen node color */ ovt: frgb_t; /* origen node transparency */ char *ovl; /* origen node label */ bool_t ove; REAL dvr; /* destine node radius */ dvc: frgb_t; /* destine node color */ dvt: frgb_t; /* destine node transparency */ char *dvl; /* destine node label */ bool_t dve; REAL era; /* @{edge->?} radius */ eco: frgb_t; /* @{edge->?} color */ eta: frgb_t; /* @{edge->?} transparency */ bool_t eex; /* @{edge->?} exists */ INTEGER ero; /* @{edge->?} root */ fco: frgb_t; /* wall color */ fta: frgb_t; /* wall transparency */ bool_t fex; /* wall exists */ INTEGER fro; /* wall root */ bool_t mid; /* TRUE iff the topological tetrahedron is 1x2 */ bool_t side; /* indicate the side of the topological tetrahedron 1x2 */ bool_t net; /* simulates a grade with thin cylindres and spheres */ ) void SetNode( Node v; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL r; /* radius */ char *l; /* label */ ) { v->exists = e; v.color = c; v.transp = t; v.label = l; v.radius = r; } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) with ( ){ t->exists = FALSE; } } SetGhostWall; void NewSetTriangle( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ INTEGER r; /* root */ ) { Wall_t f = PWall(b) { ){ f->exists = e; f.color = c; f.transp = t; f->root = r; } } NewSetTriangle; void NewSetEdge( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL ra; /* radius */ INTEGER ro; /* root */ ) { ??? ee = NARROW(PEdge(b), @{Edge->?}); { ){ ee->exists = e; ee.color = c; ee.transp = t; ee.radius = ra; ee->root = ro; } } NewSetEdge; { /* set the origin of the @place ca.e[0] */ SetNode(Org(a), ove, ovc, ovt, ovr, ovl); /* set the origin of the @place Clock(ca.e[0]) */ SetNode(Org(Clock(a)), eex, eco, eta, era, "VE"); /* set the edge component of the topological tetrahedron */ NewSetEdge(a, eex, eco, eta, era, ero); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetNode(Org(Clock(b)), dve, dvc, dvt, dvr, dvl); NewSetEdge(b, eex, eco, eta, era, ero); } if (! mid) { SetGhostWall(a); SetGhostWall(NextF(a)); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); SetGhostWall(NextF(b)); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } if (net) { Edge_t X = PEdge(PrevE(PrevF(a))); Edge_t Y = PEdge(NextE(PrevF(a))); Place_t Z = Clock(PrevE(NextF(NextE(a)))); Edge_t W = PEdge(NextE(PrevF(Z))); Node_t S = OrgV(PrevE(PrevF(a))); with ( double co = (frgb_t){1.00,1.000,0.500}, /* color, transparency and radius */ double tp = (frgb_t){0.00,0.000,0.000}, /* of the thin cylinder and sohere*/ double ra = 0.0025 ){ X->exists = TRUE; Y->exists = TRUE; W->exists = TRUE; S->exists = TRUE; X.color = co; X.radius = ra; X.transp = tp; Y.color = co; Y.radius = ra; Y.transp = tp; W.color = co; W.radius = ra; W.transp = tp; S.color = co; S.radius = ra; S.transp = tp; } } } else if (mid){ if (side) { SetGhostWall(a); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } } else { SetGhostWall(PrevF(a)); NewSetTriangle(a, fex, fco, fta, fro); Place_t an = Clock(PrevE(PrevF(NextE(PrevF(a))))); { SetGhostWall(an); NewSetTriangle(PrevF(an), fex, fco, fta, fro); } } } } /* END SetPrimal */ PROCEDURE SetDual(Place_t @p, char *vlt; char *vlf; bool_t mid; bool_t side; ) void SetNode(Node_t v; char *label) { ??? vv = (Node_t)(v); { ){ vv->exists = FALSE; vv.label = label; } } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) with ( ){ t->exists = FALSE; } } SetGhostWall; PROCEDURE SetGhostEdge(Place_t @p) == { ??? t = NARROW(PEdge(a), Edge_t); with ( ){ t->exists = FALSE; } } SetGhostEdge; void SetRowedge(d: Place_t; r: uint) Place_t dn = d; VAR { if (r == 3) { for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } } dn = PrevF(dn); SetGhostEdge(NextE(dn)); SetGhostEdge(PrevE(dn)); } } else if (r == 2){ for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } dn = NextE(dn); } dn = PrevF(dn); SetGhostEdge(NextE(dn)); } } } SetRowedge; void SetRowTriangle(b: Place_t) { for (i = 0; i < 3; i++) { SetGhostWall(b); b = PrevF(b); } } SetRowTriangle; { if ((mid) && (side)){ SetNode(Org(a), vlf); SetNode(Org(Clock(a)), vlt); SetRowTriangle(a); SetRowedge(a,3); } else if ((mid) && (NOT side)){ SetNode(Org(a), vlt); SetNode(Org(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); } else if (! mid){ SetNode(Org(a), vlt); SetNode(Org(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); Place_t an = PrevE(NextF(NextE(a))); { SetNode(Org(an),vlt); SetRowTriangle(an); SetRowedge(Clock(an),2); } } } /* END SetDual */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->fixed = argparser_keyword_present(pp, "-fixed"); o->net = argparser_keyword_present(pp, "-net"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: RootBarycenter" \ " -inFile -outFile \\\n" \ " [ -fixed ] [ -net ] \n"); END¦ } } return o; } /* END GetOptions */ bool_t IsMapWithBorder(ElemTableRec_t *top) { for (i = 0; i < top->wall.nelE; i++){ ??? a = top->wedge[i]; ??? n = Pneg(a); ??? p = Ppos(a); { if ((n == NULL) && (p == NULL)){ return TRUE; }; } } return FALSE; } /* END IsMapWithBorder */ { DoIt() } RootBarycenter. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ Bary_Corner Bary_CCorner Bary_SetCorner // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Round.c /* See {Round.h} */ // #INCLUDE #include REAL *a,b,c,d; { a = 79.499; b = 202.50; c = 38.51; d = 142.4; fprintf(Stdio.stdout, " a == " & Fmt.Int(ROUND(a)) \ " b == " & Fmt.Int(ROUND(b)) \ " c == " & Fmt.Int(ROUND(c)) \ " d == " & Fmt.Int(ROUND(d)) & "\n"); } Round. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/SelectSubdivision.c #define PROG_NAME "SelectSubdivision" #define PROG_DESC "???" #define PROG_VERS "1.0" #define SelectSubdivision_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This module implements the "selective subdivision" of the k-elements ( 1 <= k <=3) of a given 3D cellular map that are involved in geometric degeneracies. The option "element" allows to choose the selective subdivision of the k-element. The selective subdivision of a k-element also propagates the subdivision of their star (neighbors elements). */ #define SelectSubdivision_C_author \ "Implemented by L. P. Lozada.\n" \ "Revisions:\n" \ " 08-06-2000: Fixed and removed a bug that increases the number of\n" \ " original elements.\n" \ " 11-06-2000: Added the heredity of the root attributes for edges\n" \ " and walls, and we optimize the code. Hide the new elements\n" \ " insert in the refiment process:\n" \ " walls, edges and nodes are set with the attibute \n" \ " {exists=FALSE}." // #INCLUDE #include #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE uint NVE = 0; NVF: uint = 0; NVP: uint = 0; TYPE double Element = { @{Edge->?}, Wall, Tetrahedron }; typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ Element element; char *elename; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { if (o->element == Element.edge) { /* Rescue the overall attributes of the triangulation */ for (i = 0; i < top->wall.nelE; i++) { ??? p = top->wedge[i]; Edge_t e = PEdge(p); with (en == e->num, double f = PWall(p), fn == f->num ){ if (top->wall[fn]->exists ){ PWall(p)->exists = TRUE; } else { PWall(p)->exists = FALSE; } if (top->edge[en]->exists ){ PEdge(p)->exists = TRUE; } else { PEdge(p)->exists = FALSE; } PWall(p)->root = top->wall[fn]->root; PEdge(p)->root = top->edge[en]->root; } }; /* Subdivision of degenerative @{edge->?}s */ fprintf(stderr, "Eliminating degenerative @{edge->?}s\n"); for (j = 0; j < top->NE; j++) { ??? e = top->edge[j]; { if (e.degenerate) { ??? a = e.pa; ??? dfr = Octf.DegreeOfWall(a); { Subdivide@{Edge->?}(a,dfr,top); } } } } } if (o->element == Element.Wall) { /* Rescue the overall attributes of the triangulation */ for (i = 0; i < top->wall.nelE; i++) { ??? p = top->wedge[i]; Edge_t e = PEdge(p); with (en == e->num, double f = PWall(p), fn == f->num ){ PWall(p)->root = top->wall[fn]->root; PEdge(p)->root = top->edge[en]->root; } }; /* Subdivision of degenerative walls */ fprintf(stderr, "Eliminating degenerative walls\n"); for (j = 0; j < top->wall.ne; j++) { ??? f = top->wall[j]; ??? a = f.pa; { if (f.degenerate) { SubdivideWall(a,top); } } } } if (o->element == Element.Tetrahedron) { /* Rescue the overall attributes of the triangulation */ for (i = 0; i < top->wall.nelE; i++) { ??? p = top->wedge[i]; Edge_t e = PEdge(p); with (en == e->num, double f = PWall(p), fn == f->num ){ PWall(p)->root = top->wall[fn]->root; PEdge(p)->root = top->edge[en]->root; } }; /* Subdivision of degenerative tetrahedra */ fprintf(stderr, "Eliminating degenerative tetrahedra\n"); for (j = 0; j < top->cell.ne; j++) { ??? p = top->cell[j]; ??? r = Srot(top->cell[j]); Place_t a = Tors(r); { if (p.degenerate) { SubdivideTetrahedron(a,top); } } } } ??? newtop = MakeElemTable(top->wedge[0]); ??? nc = GenCoords(newtop)^; ??? cmt = "Created by Selective Subdivision of " & o->elename & " : " \ o->outFile; { WriteTopology(o->outFile, newtop, cmt & ".tp\n" & "on " & Today()); WriteState(o->outFile,newtop,nc, cmt & ".st\n" & "on "&Today() & "\nRandom Geometry"); WriteMaterials(o->outFile, newtop, cmt & ".ma\n" & "on " & Today()); } return 0; } PROCEDURE Subdivide@{Edge->?}( Place_t @pn; uint n; ElemTableRec_t *top; ) == VAR @{Node->?} x; a,bn,m1,m2,m3,t0,t1,Place_vec_t t2; wn,p: REF ARRAY OF @{Node->?}; { a = NEW(REF Place_vec_t,n); bn = NEW(REF Place_vec_t,n); m1 = NEW(REF Place_vec_t,n); m2 = NEW(REF Place_vec_t,n); m3 = NEW(REF Place_vec_t,n); t0 = NEW(REF Place_vec_t,n); t1 = NEW(REF Place_vec_t,n); t2 = NEW(REF Place_vec_t,n); /* save the @places */ a = NEW(REF Place_vec_t,n); a[0] = an; ??? f = PWedge(a[0]).wall; ??? e = PEdge(a[0]); ??? ee = PEdge(NextE(a[0])); ??? ee_ = PEdge(PrevE(a[0])); { if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; f->root = top->wall[f->num]->root; if (top->edge[e->num]->exists ){ e->exists = TRUE; } else { e->exists = FALSE; } e.color = top->edge[e->num].color; e.transp = top->edge[e->num].transp; e.radius = top->edge[e->num].radius; e->root = top->edge[e->num]->root; if (top->edge[ee->num]->exists ){ ee->exists = TRUE; } else { ee->exists = FALSE; } ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; ee->root = top->edge[e->num]->root; if (top->edge[ee_->num]->exists ){ ee_->exists = TRUE; } else { ee_->exists = FALSE; } ee_.color = top->edge[ee_->num].color; ee_.transp = top->edge[ee_->num].transp; ee_.radius = top->edge[ee_->num].radius; ee_->root = top->edge[ee_->num]->root; } for (i = 1; i < n; i++) { a[i] = NextF(a[i-1]); ??? f = PWedge(a[i]).wall; ??? ee = PEdge(NextE(a[i])); ??? ee_ = PEdge(PrevE(a[i])); { if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; f->root = top->wall[f->num]->root; if (top->edge[ee->num]->exists ){ ee->exists = TRUE; } else { ee->exists = FALSE; } ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; ee->root = top->edge[ee->num]->root; if (top->edge[ee_->num]->exists ){ ee_->exists = TRUE; } else { ee_->exists = FALSE; } ee_.color = top->edge[ee_->num].color; ee_.transp = top->edge[ee_->num].transp; ee_.radius = top->edge[ee_->num].radius; ee_->root = top->edge[ee_->num]->root; } } /* save the nodes */ wn = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { wn[i] = Org(PrevE(a[i])); } /* save the tetrahedra */ p = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { p[i] = Pneg(a[i]); } /* save other @places */ bn = NEW(REF Place_vec_t,n); for (i = 0; i < n; i++) { bn[i] = Clock(PrevE(NextF(PrevE(a[i])))); ??? e = PEdge(bn[i]); ??? f = PWedge( bn[i]).wall; { if (top->edge[e->num]->exists ){ e->exists = TRUE; } else { e->exists = FALSE; } e.color = top->edge[e->num].color; e.transp = top->edge[e->num].transp; e.radius = top->edge[e->num].radius; e->root = top->edge[e->num]->root; if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; f->root = top->wall[f->num]->root; } } /* insert new places */ for (i = 0; i < n; i++) { m1[i] = MakeWedge(); /* @{edge->?} component always FALSE */ m2[i] = MakeWedge(); /* @{edge->?} component will depend */ m3[i] = MakeWedge(); /* @{edge->?} component always FALSE */ t0[i] = MakeTriangle(); /* @{edge->?} component will depend */ t1[i] = NextE(t0[i]); /* @{edge->?} component always FALSE */ t2[i] = NextE(t1[i]); /* @{edge->?} component always FALSE */ ??? f0 = PWedge(t0[i]).wall; ??? f1 = PWedge(t1[i]).wall; ??? f2 = PWedge(t2[i]).wall; ??? e0 = PEdge(t0[i]); ??? e1 = PEdge(t1[i]); ??? e2 = PEdge(t2[i]); with ( double em1 = PEdge(m1[i]); double em2 = PEdge(m2[i]); double em3 = PEdge(m3[i]); double fm1 = PWedge(m1[i]).wall; double fm2 = PWedge(m2[i]).wall; double fm3 = PWedge(m3[i]).wall ){ /* with respect to m1[i], m2[i] and m3[i] */ /* @{edge->?}s */ em1->exists = FALSE; em3->exists = FALSE; if ((PEdge(a[i])->exists )){ em2->exists = TRUE; } else { em2->exists = FALSE; } em2->root = PEdge(a[i])->root; /* walls */ if ((PWedge(a[i]).wall->exists )){ fm1->exists = TRUE; fm2->exists = TRUE; fm3->exists = TRUE; } else { fm1->exists = FALSE; fm2->exists = FALSE; fm3->exists = FALSE; } /* with respect to insert wall */ /* @{edge->?}s */ e1->exists = FALSE; e2->exists = FALSE; if ((PEdge(bn[i])->exists )){ e0->exists = TRUE; } else { e0->exists = FALSE; } /* walls */ f0->exists = FALSE; f1->exists = FALSE; f2->exists = FALSE; } } /* Now, subdivide @{edge->?} and extend the subdivision on the edge's stars */ x = MakeNode(); ??? v = (Node_t)(x); { ){ v.label = "VE"; if ((PEdge(a[0])->exists)) { v->exists = TRUE; v.radius = PEdge(a[0]).radius; v.color = PEdge(a[0]).color; v.transp = PEdge(a[0]).transp; } else { v->exists = FALSE; } v->num = NVE; NVE++; } for (j = 0; j < n; j++) { Place_t b = NextE(a[j]); Edge_t be = PEdge(b); Place_t c = NextE(b); Edge_t ce = PEdge(c); ??? u = Org(a[j]); ??? v = Org(b); ??? w = Org(c); with ( /* save the attributes of the edge-wall component of the @place a[j] */ double f = PWedge(a[j]).wall; double fn = f->num; double ff = top->wall[fn]; double fe = ff->exists; double fc = ff.color; double ft = ff.transp; double g = PWedge(m3[j]).wall; double ge = g->exists; double gc = g.color; double gt = g.transp; double p = PWedge(m1[j]).wall; double pe = p->exists; double pc = p.color; double pt = p.transp; double h = PEdge(m3[j]) ){ SetNextE(a[j],m1[j]); SetNextE(m1[j],c); SetNextE(m2[j],m3[j]); SetNextE(m3[j],Clock(b)); SetOrg(a[j], u); SetOrg(Clock(a[j]), x); SetOrg(m2[j],v); SetOrg(Clock(m2[j]), x); SetOrg(m3[j], x); SetOrg(Clock(m3[j]), w); SetOrg(m1[j], x); SetOrg(Clock(m1[j]), w); SetNextF(m1[j],m3[j]); /* set the attributes for the wall component */ SetRingWallInfo(a[j],f); SetRingWallInfo(m3[j],g); if (fe) { ge = TRUE; pe = TRUE; } else { ge = FALSE; pe = FALSE; } gc = fc; pc = fc; gt = ft; pt = ft; SetRingEdgeInfo(m3[j],h); SetRingEdgeInfo(b,be); SetRingEdgeInfo(c,ce); SetRingWallInfo(bn[j],PWedge(bn[j]).wall); SetRingWallInfo(NextF(bn[j]),PWedge(NextF(bn[j])).wall); } } for (j = 0; j < n; j++) { SetNextF(Clock(m2[j]),Clock(m2[(j+1) % n])); } ??? k = PEdge(m2[0]); ??? q = PWedge(m2[0]).wall; ??? f = PWedge(a[0]).wall; ??? e = PEdge(a[0]); ??? en = e->num; ??? ea = top->edge[en]; ??? ee = ea->exists; ??? er = ea.radius; ??? ec = ea.color; ??? et = e.transp; ??? fn = f->num; ??? fa = top->wall[fn]; ??? fe = fa->exists; ??? fc = fa.color; ??? ft = fa.transp; ??? ke = k->exists; ??? kr = k.radius; ??? kc = k.color; ??? kt = k.transp; ??? qe = q->exists; ??? qc = q.color; ??? qt = q.transp; { if (ee){ ke = TRUE; }else{ ke = FALSE; } kr = er; kc = ec; kt = et; SetRingEdgeInfo(a[0],e); SetRingEdgeInfo(m2[0],k); if (fe){ qe = TRUE; }else{ qe = FALSE; } qc = fc; qt = ft; } for (j = 0; j < n; j++) { Place_t cn = NextF(bn[j]); ??? e1 = PEdge(t1[j]); ??? e2 = PEdge(t2[j]); Wall_t cnf = PWall(cn); Edge_t cne = PEdge(cn); { if (top->wall[cnf->num]->exists ){ cnf->exists = TRUE; } else { cnf->exists = FALSE; } cnf.color = top->wall[cnf->num].color; cnf.transp = top->wall[cnf->num].transp; if (top->edge[cne->num]->exists ){ cne->exists = TRUE; } else { cne->exists = FALSE; } cne.color = top->edge[cne->num].color; cne.transp = top->edge[cne->num].transp; cne.radius = top->edge[cne->num].radius; /* set the origins */ SetOrgAll(t0[j],wn[j]); SetOrgAll(t1[j],wn[(j+1) % n]); SetOrgAll(t2[j],x); SetNextF(bn[j], t0[j]); SetNextF(t0[j],cn); SetNextF(m1[j],t2[j]); SetNextF(t2[j],m3[j]); SetNextF(Clock(m1[(j+1) % n]), t1[j]); SetNextF(t1[j],Clock(m3[(j+1) % n])); SetRingEdgeInfo(t0[j],PEdge(cn)); SetRingEdgeInfo(t1[j],e1); SetRingEdgeInfo(t2[j],e2); } } /* insert cells */ for (j = 0; j < n; j++) { ??? q = Triangulation.MakeCell(); { SetPnegOfNearbyWalls(a[j],p[j]); SetPnegOfNearbyWalls(m2[j],q); } } } /* END Subdivide@{Edge->?} */ PROCEDURE SubdivideWall(Place_t @p, ElemTableRec_t *top) /* Subdivide a degenerative triangular wall in three new walls through the insertion of a new medial node of type "VF" and six wall-@{edge->?} @places. Then, expand this subdivision on the wall's star. */ VAR @{Node->?} x; { /* Create the medial node "VF" */ x = MakeNode(); ??? v = (Node_t)(x); { ){ v->exists= FALSE; v.label = "VF"; v->num = NVF; NVF++; } Wall_t fa = PWall(a); Edge_t ea = PEdge(a); Place_t b = NextE(a); Edge_t eb = PEdge(b); Place_t c = PrevE(a); Edge_t ec = PEdge(c); Place_t af = NextF(a); Place_t bf = NextF(b); Place_t cf = NextF(c); Place_t af_ = PrevF(a); Place_t bf_ = PrevF(b); Place_t cf_ = PrevF(c); Edge_t eaf = PEdge(PrevE(af)); Edge_t eaf_ = PEdge(PrevE(af_)); Wall_t faf = PWall(af); Wall_t faf_ = PWall(af_); Edge_t ebf = PEdge(PrevE(bf)); Edge_t ebf_ = PEdge(PrevE(bf_)); Wall_t fbf = PWall(bf); Wall_t fbf_ = PWall(bf_); Edge_t ecf = PEdge(PrevE(cf)); Edge_t ecf_ = PEdge(PrevE(cf_)); Wall_t fcf = PWall(cf); Wall_t fcf_ = PWall(cf_); ??? u = Org(a); ??? v = Org(b); ??? w = Org(c); Place_t d = MakeWedge(); Place_t e = MakeWedge(); Place_t f = MakeWedge(); Place_t g = MakeWedge(); Place_t h = MakeWedge(); Place_t i = MakeWedge(); Wall_t df = PWall(d); Wall_t ff = PWall(f); Wall_t hf = PWall(h); with ( /* new walls to insert on the wall's star */ f1 == MakeTriangle(), f2 == MakeTriangle(), f3 == MakeTriangle(), f4 == MakeTriangle(), f5 == MakeTriangle(), f6 == MakeTriangle(), double q1 = MakeCell(); double q2 = MakeCell(); double q3 = MakeCell(); double q4 = MakeCell(); double q5 = MakeCell(); double q6 = MakeCell() ){ ??? t = top->wall[fa->num]; ??? tc = t.color; ??? tt = t.transp; ??? tr = t->root; { if (t->exists) { df->exists = TRUE; ff->exists = TRUE; hf->exists = TRUE; df.color = tc; df.transp = tt; df->root = tr; ff.color = tc; ff.transp = tt; ff->root = tr; hf.color = tc; hf.transp = tt; hf->root = tr; } else { df->exists = FALSE; ff->exists = FALSE; hf->exists = FALSE; df->root = tr; ff->root = tr; hf->root = tr; } } /* first link connecting the @place "a" */ SetNextE(a,d); SetNextE(d,e); SetNextE(e,a); SetRingWallInfo(d,df); /* second link connecting the @place "b" */ SetNextE(b,f); SetNextE(f,g); SetNextE(g,b); SetRingWallInfo(f,ff); /* third link connecting the @place "c" */ SetNextE(c,h); SetNextE(h,i); SetNextE(i,c); SetRingWallInfo(h,hf); /* save information about the original edges "PEdge(a)": "ea" */ ea->exists = top->edge[ea->num]->exists; ea.color = top->edge[ea->num].color; ea.transp = top->edge[ea->num].transp; ea.radius = top->edge[ea->num].radius; /* save information about the original edges "PEdge(b)": "eb" */ eb->exists = top->edge[eb->num]->exists; eb.color = top->edge[eb->num].color; eb.transp = top->edge[eb->num].transp; eb.radius = top->edge[eb->num].radius; /* save information about the original edges "PEdge(c)": "ec" */ ec->exists = top->edge[ec->num]->exists; ec.color = top->edge[ec->num].color; ec.transp = top->edge[ec->num].transp; ec.radius = top->edge[ec->num].radius; /* save information about the wall "PWall(af)" : "faf" */ faf->exists = top->wall[faf->num]->exists; faf.color = top->wall[faf->num].color; faf.transp = top->wall[faf->num].transp; /* save information about the edge "PEdge(af)" : "eaf" */ eaf->exists = top->edge[eaf->num]->exists; eaf.color = top->edge[eaf->num].color; eaf.transp = top->edge[eaf->num].transp; eaf.radius = top->edge[eaf->num].radius; /* save information about the wall "PWall(af_)" : "faf_" */ faf_->exists = top->wall[faf_->num]->exists; faf_.color = top->wall[faf_->num].color; faf_.transp= top->wall[faf_->num].transp; /* save information about the edge "PEdge(af_)" : "eaf_" */ eaf_->exists = top->edge[eaf_->num]->exists; eaf_.color = top->edge[eaf_->num].color; eaf_.transp = top->edge[eaf_->num].transp; eaf_.radius = top->edge[eaf_->num].radius; /* save information about the wall "PWall(bf)" : "fbf" */ fbf->exists = top->wall[fbf->num]->exists; fbf.color = top->wall[fbf->num].color; fbf.transp= top->wall[fbf->num].transp; /* save information about the edge "PEdge(bf)" : "ebf" */ ebf->exists = top->edge[ebf->num]->exists; ebf.color = top->edge[ebf->num].color; ebf.transp = top->edge[ebf->num].transp; ebf.radius = top->edge[ebf->num].radius; /* save information about the wall "PWall(bf_)" : "fbf_" */ fbf_->exists= top->wall[fbf_->num]->exists; fbf_.color = top->wall[fbf_->num].color; fbf_.transp= top->wall[fbf_->num].transp; /* save information about the edge "PEdge(bf_)" : "ebf_" */ ebf_->exists = top->edge[ebf_->num]->exists; ebf_.color = top->edge[ebf_->num].color; ebf_.transp = top->edge[ebf_->num].transp; ebf_.radius = top->edge[ebf_->num].radius; /* save information about the wall "PWall(cf)" : "fcf" */ fcf->exists = top->wall[fcf->num]->exists; fcf.color = top->wall[fcf->num].color; fcf.transp= top->wall[fcf->num].transp; /* save information about the edge "PEdge(cf)" : "ecf" */ ecf->exists = top->edge[ecf->num]->exists; ecf.color = top->edge[ecf->num].color; ecf.transp = top->edge[ecf->num].transp; ecf.radius = top->edge[ecf->num].radius; /* save information about the wall "PWall(cf_)" : "fcf_" */ fcf_->exists = top->wall[fcf_->num]->exists; fcf_.color = top->wall[fcf_->num].color; fcf_.transp= top->wall[fcf_->num].transp; /* save information about the edge "PEdge(cf_)" : "ecf_" */ ecf_->exists = top->edge[ecf_->num]->exists; ecf_.color = top->edge[ecf_->num].color; ecf_.transp = top->edge[ecf_->num].transp; ecf_.radius = top->edge[ecf_->num].radius; /* set the attributes for the internal walls */ PWall(f1)->exists = FALSE; PWall(f2)->exists = FALSE; PWall(f3)->exists = FALSE; PWall(f4)->exists = FALSE; PWall(f5)->exists = FALSE; PWall(f6)->exists = FALSE; /* Now make the connections in the interior of wall */ SetNextF(g,Clock(d)); SetNextF(i,Clock(f)); SetNextF(e,Clock(h)); /* Now subdivide the "Ppos(a)" tetrahedron ( the superior tetrahedron in my plan */ /* first we, insert f1 */ SetNextF(d, Clock(f1)); SetNextF(Clock(f1), Clock(g)); assert(NextF(Clock(g)) == d); SetNextF(NextE(f1),NextE(af)); SetNextF(Clock(PrevE(bf)), NextE(f1)); /* now, we insert f2 */ SetNextF(f, Clock(f2)); SetNextF(Clock(f2), Clock(i)); assert(NextF(Clock(i)) == f); SetNextF(NextE(f2),NextE(bf)); SetNextF(Clock(PrevE(cf)), NextE(f2)); /* now, we insert f3 */ SetNextF(h, Clock(f3)); SetNextF(Clock(f3), Clock(e)); assert(NextF(Clock(e)) == h); SetNextF(NextE(f3),NextE(cf)); SetNextF(Clock(PrevE(af)), NextE(f3)); /* now make connections between the internal walls inserted */ SetNextF(PrevE(f1),PrevE(f3)); SetNextF(PrevE(f3),PrevE(f2)); assert(NextF(PrevE(f2)) == PrevE(f1)); /* set the superior axial @{edge->?} */ SetRingEdgeInfo(PrevE(f1), PEdge(PrevE(f1))); /* OK */ PEdge(PrevE(f1))->exists = FALSE; /* Now subdivide the "Pneg(a)" tetrahedron ( the inferior tetrahedron in my plan */ /* now, we insert f4 */ SetNextF(Clock(g), Clock(f4)); assert(NextF(Clock(f4)) == d); SetNextF(NextE(af_), NextE(f4)); SetNextF(NextE(f4), Clock(PrevE(bf_))); /* now, we insert f5 */ SetNextF(Clock(i), Clock(f5)); assert(NextF(Clock(f5)) == f); SetNextF(NextE(bf_), NextE(f5)); SetNextF(NextE(f5), Clock(PrevE(cf_))); /* now, we insert f6 */ SetNextF(Clock(e), Clock(f6)); assert(NextF(Clock(f6)) == h); SetNextF(NextE(cf_), NextE(f6)); SetNextF(NextE(f6), Clock(PrevE(af_))); /* now make connections between the internal walls inserted */ SetNextF(PrevE(f4),PrevE(f5)); SetNextF(PrevE(f5),PrevE(f6)); assert(NextF(PrevE(f6)) == PrevE(f4)); /* set the inferior axial @{edge->?} */ SetRingEdgeInfo(PrevE(f4), PEdge(PrevE(f4))); /* OK */ PEdge(PrevE(f4))->exists = FALSE; /* set the origins */ SetOrgAll(f1, x); SetOrgAll(a, u); SetOrgAll(b, v); SetOrgAll(c, w); SetOrgAll(PrevE(f1), OrgV(PrevE(af))); SetOrgAll(PrevE(f4), OrgV(PrevE(af_))); /* set the new internal @{edge->?}s */ SetRingEdgeInfo(f1,PEdge(f1)); PEdge(f1)->exists = FALSE; SetRingEdgeInfo(f2,PEdge(f2)); PEdge(f2)->exists = FALSE; SetRingEdgeInfo(f3,PEdge(f3)); PEdge(f3)->exists = FALSE; /* set the original edgess and walls in the superior level */ SetRingEdgeInfo(PrevE(af),eaf); SetRingEdgeInfo(PrevE(bf),ebf); SetRingEdgeInfo(PrevE(cf),ecf); SetRingWallInfo(af,faf); SetRingWallInfo(bf,fbf); SetRingWallInfo(cf,fcf); /* set the original edgess and walls in the inferior label */ SetRingEdgeInfo(PrevE(af_),eaf_); SetRingEdgeInfo(PrevE(bf_),ebf_); SetRingEdgeInfo(PrevE(cf_),ecf_); SetRingWallInfo(af_,faf_); SetRingWallInfo(bf_,fbf_); SetRingWallInfo(cf_,fcf_); /* set the original edgess in the half label */ SetRingEdgeInfo(a,ea); SetRingEdgeInfo(b,eb); SetRingEdgeInfo(c,ec); SetPnegOfNearbyWalls(Clock(PrevE(f1)),q1); SetPnegOfNearbyWalls(Clock(PrevE(f2)),q2); SetPnegOfNearbyWalls(Clock(PrevE(f3)),q3); SetPnegOfNearbyWalls(PrevE(f4),q4); SetPnegOfNearbyWalls(PrevE(f5),q5); SetPnegOfNearbyWalls(PrevE(f6),q6); } } /* END SubdivideWall */ PROCEDURE SubdivideTetrahedron(Place_t @p, ElemTableRec_t *top) /* Subdivide a degenerative tetrahedron in four new tetrahedra through the insertion of a new medial node of type "VP" more six walls and three @{edge->?}s. */ @{Node->?} *y; { /* Create the medial node "VP" */ y = MakeNode(); ??? v = (Node_t)(y); { ){ v->exists= FALSE; v.label = "VP"; v->num = NVP; NVP++; } Place_t b = PrevF(a); Place_t c = PrevE(b); Place_t d = NextF(c); Place_t e = PrevE(a); Place_t f = PrevF(e); Place_t g = PrevE(f); Place_t h = NextF(g); Wall_t fa = PWall(a); Wall_t fb = PWall(b); Wall_t fg = PWall(g); Wall_t fh = PWall(h); Edge_t ea = PEdge(a); Edge_t ec = PEdge(c); Edge_t ee = PEdge(e); Edge_t eh = PEdge(h); Edge_t eeb = PEdge(NextE(b)); Edge_t eea = PEdge(NextE(a)); Place_t i = NextE(a); Place_t j = PrevF(i); Place_t k = NextE(b); Place_t l = NextF(k); ??? u = Org(a); ??? v = Org(Clock(a)); ??? w = Org(c); ??? x = Org(e); ??? f1 = MakeTriangle(); ??? f2 = MakeTriangle(); ??? f3 = MakeTriangle(); ??? f4 = MakeTriangle(); ??? f5 = MakeTriangle(); ??? f6 = MakeTriangle(); Cell_t q1 = MakeCell(); Cell_t q2 = MakeCell(); Cell_t q3 = MakeCell(); Cell_t q4 = MakeCell(); { /* save attributes for the original walls: "fa", "fb", "fg", "fh". */ fa->exists = top->wall[fa->num]->exists; fa.color = top->wall[fa->num].color; fa.transp = top->wall[fa->num].transp; fb->exists = top->wall[fb->num]->exists; fb.color = top->wall[fb->num].color; fb.transp = top->wall[fb->num].transp; fg->exists = top->wall[fg->num]->exists; fg.color = top->wall[fg->num].color; fg.transp = top->wall[fg->num].transp; fh->exists = top->wall[fh->num]->exists; fh.color = top->wall[fh->num].color; fh.transp = top->wall[fh->num].transp; /* save attributes for the original edgess: "ea", "ec", "ee", "eh", "eeb", and "eea". */ ea->exists = top->edge[ea->num]->exists; ea.color = top->edge[ea->num].color; ea.transp = top->edge[ea->num].transp; ea.radius = top->edge[ea->num].radius; ec->exists = top->edge[ec->num]->exists; ec.color = top->edge[ec->num].color; ec.transp = top->edge[ec->num].transp; ec.radius = top->edge[ec->num].radius; ee->exists = top->edge[ee->num]->exists; ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; eh->exists = top->edge[eh->num]->exists; eh.color = top->edge[eh->num].color; eh.transp = top->edge[eh->num].transp; eh.radius = top->edge[eh->num].radius; eea->exists = top->edge[eea->num]->exists; eea.color = top->edge[eea->num].color; eea.transp = top->edge[eea->num].transp; eea.radius = top->edge[eea->num].radius; eeb->exists = top->edge[eeb->num]->exists; eeb.color = top->edge[eeb->num].color; eeb.transp = top->edge[eeb->num].transp; eeb.radius = top->edge[eeb->num].radius; /* set the attributes for the new internal walls */ PWall(f1)->exists = FALSE; PWall(f2)->exists = FALSE; PWall(f3)->exists = FALSE; PWall(f4)->exists = FALSE; PWall(f5)->exists = FALSE; PWall(f6)->exists = FALSE; /* insert f1 */ SetNextF(b,f1); SetNextF(f1,a); /* insert f2 */ SetNextF(c,f2); SetNextF(f2,d); /* insert f3 */ SetNextF(f,f3); SetNextF(f3,e); /* set the relations among f1,f2 and f3 */ SetNextF(Clock(NextE(f2)),PrevE(f1)); SetNextF(PrevE(f1),Clock(NextE(f3))); SetNextF(Clock(NextE(f3)),Clock(NextE(f2))); SetRingEdgeInfo(PrevE(f1), PEdge(PrevE(f1))); PEdge(PrevE(f1))->exists = FALSE; /* insert f4 */ SetNextF(j,f4); SetNextF(f4,i); /* insert f5 */ SetNextF(k,f5); SetNextF(f5,l); /* insert f6 */ SetNextF(g,f6); SetNextF(f6,h); /* set the internal relations along @{edge->?} "yv" */ SetNextF(PrevE(f5),PrevE(f4)); SetNextF(PrevE(f4),Clock(NextE(f1))); SetNextF(Clock(NextE(f1)), PrevE(f5)); SetRingEdgeInfo(Clock(NextE(f1)),PEdge(Clock(NextE(f1)))); PEdge(NextE(f1))->exists = FALSE; /* set the internal relations along @{edge->?} "wy" */ SetNextF(NextE(f5),Clock(PrevE(f6))); SetNextF(Clock(PrevE(f6)),Clock(PrevE(f2))); SetNextF(Clock(PrevE(f2)),NextE(f5)); SetRingEdgeInfo(NextE(f5),PEdge(NextE(f5))); PEdge(NextE(f5))->exists = FALSE; /* set the internal relations along @{edge->?} "xy" */ SetNextF(NextE(f6), NextE(f4)); SetNextF(NextE(f4), Clock(PrevE(f3))); SetNextF(Clock(PrevE(f3)), NextE(f6)); SetRingEdgeInfo(NextE(f4), PEdge(NextE(f4))); PEdge(NextE(f4))->exists = FALSE; /* set the overall @{edge->?} component */ SetRingEdgeInfo(a, ea); SetRingEdgeInfo(c, ec); SetRingEdgeInfo(e, ee); SetRingEdgeInfo(i, eea); SetRingEdgeInfo(k, eeb); SetRingEdgeInfo(h, eh); SetRingWallInfo(a, fa); SetRingWallInfo(b, fb); SetRingWallInfo(g, fg); SetRingWallInfo(h, fh); /* set the origins */ SetOrgAll(a,u); SetOrgAll(Clock(a),v); SetOrgAll(c,w); SetOrgAll(e,x); SetOrgAll(PrevE(f1),y); /* set the cells */ SetPnegOfNearbyWalls(a,q1); SetPnegOfNearbyWalls(Spin(b),q2); SetPnegOfNearbyWalls(Spin(g),q3); SetPnegOfNearbyWalls(Spin(f6),q4); } } /* END SubdivideTetrahedron */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-element"); o->elename = argparser_get_next(pp); if (0 == strcmp(o->elename, "@{edge->?}"))) { o->element = Element.edge } else if (0 == strcmp(o->elename, "wall"))){ o->element = Element.Wall } else if (0 == strcmp(o->elename, "tetrahedron"))){ o->element = Element.Tetrahedron } else { argparser_error(pp, "bad element \"" & argparser_get_next(pp) & "\"\n") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: SelectSubdivision\\\n" \ " -inFile -outFile \\\n" \ " -element { @{edge->?} | wall | tetrahedron }\n"); END¦ } } return o; } /* END GetOptions */ /* UNUSED */ PROCEDURE OldSubdivide@{Edge->?}( Place_t @pn; uint n; ElemTableRec_t *top; ) == @{Node->?} x; a,bn,m1,m2,m3,t0,t1,Place_vec_t t2; wn,p: REF ARRAY OF @{Node->?}; { a = NEW(REF Place_vec_t,n); bn = NEW(REF Place_vec_t,n); m1 = NEW(REF Place_vec_t,n); m2 = NEW(REF Place_vec_t,n); m3 = NEW(REF Place_vec_t,n); t0 = NEW(REF Place_vec_t,n); t1 = NEW(REF Place_vec_t,n); t2 = NEW(REF Place_vec_t,n); /* save the @places */ a = NEW(REF Place_vec_t,n); a[0] = an; ??? f = PWedge(a[0]).wall; ??? e = PEdge(a[0]); ??? ee = PEdge(NextE(a[0])); ??? ee_ = PEdge(PrevE(a[0])); { if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; if (top->edge[e->num]->exists ){ e->exists = TRUE; } else { e->exists = FALSE; } e.color = top->edge[e->num].color; e.transp = top->edge[e->num].transp; e.radius = top->edge[e->num].radius; if (top->edge[ee->num]->exists ){ ee->exists = TRUE; } else { ee->exists = FALSE; } ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; if (top->edge[ee_->num]->exists ){ ee_->exists = TRUE; } else { ee_->exists = FALSE; } ee_.color = top->edge[ee_->num].color; ee_.transp = top->edge[ee_->num].transp; ee_.radius = top->edge[ee_->num].radius; } for (i = 1; i < n; i++) { a[i] = NextF(a[i-1]); ??? f = PWedge(a[i]).wall; ??? ee = PEdge(NextE(a[i])); ??? ee_ = PEdge(PrevE(a[i])); { if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; if (top->edge[ee->num]->exists ){ ee->exists = TRUE; } else { ee->exists = FALSE; } ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; if (top->edge[ee_->num]->exists ){ ee_->exists = TRUE; } else { ee_->exists = FALSE; } ee_.color = top->edge[ee_->num].color; ee_.transp = top->edge[ee_->num].transp; ee_.radius = top->edge[ee_->num].radius; } } /* save the nodes */ wn = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { wn[i] = Org(PrevE(a[i])); } /* save the tetrahedra */ p = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { p[i] = Pneg(a[i]); } /* save other @places */ bn = NEW(REF Place_vec_t,n); for (i = 0; i < n; i++) { bn[i] = Clock(PrevE(NextF(PrevE(a[i])))); ??? e = PEdge(bn[i]); ??? f = PWedge(bn[i]).wall; { if (top->edge[e->num]->exists ){ e->exists = TRUE; } else { e->exists = FALSE; } e.color = top->edge[e->num].color; e.transp = top->edge[e->num].transp; e.radius = top->edge[e->num].radius; if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; } } /* insert wedges and edges */ for (i = 0; i < n; i++) { m1[i] = MakeWedge(); m2[i] = MakeWedge(); m3[i] = MakeWedge(); t0[i] = MakeTriangle(); t1[i] = NextE(t0[i]); t2[i] = NextE(t1[i]); ??? f = PWedge(t0[i]).wall; ??? e0 = PEdge(t0[i]); ??? e1 = PEdge(t1[i]); ??? e2 = PEdge(t2[i]); with ( /* new tests */ double em1i = PEdge(m1[i]); double em2i = PEdge(m2[i]) ){ /* new tests */ em1i->exists = FALSE; em2i->exists = FALSE; /* end new tests */ f->exists = FALSE; f.transp = (frgb_t){1.0,1.0,1.0}; e1->exists = FALSE; e2->exists = FALSE; e1.radius = 0.003; e1.transp = (frgb_t){1.0,1.0,1.0}; e2.radius = 0.003; e2.transp = (frgb_t){1.0,1.0,1.0}; if ((PEdge(bn[i])->exists )){ e0->exists = TRUE; } else { e0->exists = FALSE; } } } /* Now, subdivide @{edge->?} and extend the subdivision on the edge's stars */ x = MakeNode(); ??? v = (Node_t)(x); { ){ v.label = "VE"; if ((PEdge(a[0])->exists)) { v.radius = PEdge(a[0]).radius; v.color = PEdge(a[0]).color; v.transp = PEdge(a[0]).transp; } else { v.radius = 0.00; v.color = (frgb_t){1.0,1.0,1.0}; v.transp = (frgb_t){1.0,1.0,1.0}; } v->num = NVE; NVE++; } for (j = 0; j < n; j++) { Place_t b = NextE(a[j]); Edge_t be = PEdge(b); Place_t c = NextE(b); Edge_t ce = PEdge(c); ??? u = Org(a[j]); ??? v = Org(b); ??? w = Org(c); with ( /* save the attributes of the edge-wall component of the @place a[j] */ double f = PWedge(a[j]).wall; double fe = f->exists; double fc = f.color; double ft = f.transp; double g = PWedge(m3[j]).wall; double ge = g->exists; double gc = g.color; double gt = g.transp; double h = PEdge(m3[j]) ){ SetNextE(a[j],m1[j]); SetNextE(m1[j],c); SetNextE(m2[j],m3[j]); SetNextE(m3[j],Clock(b)); SetOrg(a[j], u); SetOrg(Clock(a[j]), x); SetOrg(m2[j],v); SetOrg(Clock(m2[j]), x); SetOrg(m3[j], x); SetOrg(Clock(m3[j]), w); SetOrg(m1[j], x); SetOrg(Clock(m1[j]), w); SetNextF(m1[j],m3[j]); /* set the attributes for the wall component */ SetRingWallInfo(a[j],f); SetRingWallInfo(m3[j],g); if (fe) { ge = TRUE; } else { ge = FALSE; } gc = fc; gt = ft; SetRingEdgeInfo(m3[j],h); SetRingEdgeInfo(b,be); SetRingEdgeInfo(c,ce); SetRingWallInfo(PWedge(bn[j],bn[j]).wall); SetRingWallInfo(NextF(bn[j]),PWedge(NextF(bn[j])).wall); } } for (j = 0; j < n; j++) { SetNextF(Clock(m2[j]),Clock(m2[(j+1) % n])); } ??? k = PEdge(m2[0]); ??? e = PEdge(a[0]); ??? ee = e->exists; ??? er = e.radius; ??? ec = e.color; ??? et = e.transp; ??? ke = k->exists; ??? kr = k.radius; ??? kc = k.color; ??? kt = k.transp; { if (ee){ ke = TRUE; }else{ ke = FALSE; } kr = er; kc = ec; kt = et; SetRingEdgeInfo(a[0],e); SetRingEdgeInfo(m2[0],k); } for (j = 0; j < n; j++) { Place_t cn = NextF(bn[j]); ??? e1 = PEdge(t1[j]); ??? e2 = PEdge(t2[j]); Wall_t cnf = PWall(cn); Edge_t cne = PEdge(cn); { if (top->wall[cnf->num]->exists ){ cnf->exists = TRUE; } else { cnf->exists = FALSE; } cnf.color = top->wall[cnf->num].color; cnf.transp = top->wall[cnf->num].transp; if (top->edge[cne->num]->exists ){ cne->exists = TRUE; } else { cne->exists = FALSE; } cne.color = top->edge[cne->num].color; cne.transp = top->edge[cne->num].transp; cne.radius = top->edge[cne->num].radius; /* set the origins */ SetOrgAll(t0[j],wn[j]); SetOrgAll(t1[j],wn[(j+1) % n]); SetOrgAll(t2[j],x); SetNextF(bn[j], t0[j]); SetNextF(t0[j],cn); SetNextF(m1[j],t2[j]); SetNextF(t2[j],m3[j]); SetNextF(Clock(m1[(j+1) % n]), t1[j]); SetNextF(t1[j],Clock(m3[(j+1) % n])); SetRingEdgeInfo(t0[j],PEdge(cn)); SetRingEdgeInfo(t1[j],e1); SetRingEdgeInfo(t2[j],e2); } } /* insert cells */ for (j = 0; j < n; j++) { ??? q = Triangulation.MakeCell(); { SetPnegOfNearbyWalls(a[j],p[j]); SetPnegOfNearbyWalls(m2[j],q); } } } /* END OldSubdivide@{Edge->?} */ /* UNUSED */ uint Incident( Place_t b; uint n; ElemTableRec_t *top; ) /* This module indicates the number of existing walls incident to the component @{edge->?} of the @place b. */ VAR Place_t bn = b; in: uint = 0; { for (j = 0; j < n; j++){ ??? fn = PWall(bn)->num; ??? f = top->wall[fn]; { if (f->exists){ in++; } bn = NextF(bn); } } assert(bn == b); return in; } /* END Incident */ { DoIt() } SelectSubdivision. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/SplineToWire4.c #define PROG_NAME "SplineToWire4" #define PROG_DESC "???" #define PROG_VERS "1.0" #define SplineToWire4_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Given control points of a cubic spline curve, generates sample points along it. Writes the sample points as camera positions in the format expected by the "Wire4" - Interactive 4D Wireframe Display Program (".w4"). Also writes a plain text file with one point per line (preceded by its integer ID). -Include the option "renderInterval" ( between [1-10]) for generate spacing among configurations. Last Modification by stolfi 06-08-2000 */ // #INCLUDE #include // #INCLUDE #include #include // #INCLUDE // BSplineApproximation; TYPE double Row3I = ARRAY [0..2] OF INTEGER; double double = double; typedef struct Options_t { char *outFile; /* Output file name prefix */ uint ncp; /* Number of control points. */ cp: REF r4_vec_t; /* Control points for spline. */ bool_t tips; /* TRUE includes the endpoints. */ double normalize; /* If nonzero, normalize From-To vectors to this length. */ uint renderInterval; /* Subsampling ratio for camera positions. */ uint samplesPerArc; /* Number of samples per spline arc (for Wire4 plotting). */ To4: r4_t; /* Look at point */ Up4: r4_t; /* Head-up point */ Over4: r4_t; /* Hyperhead-up point */ } <* FATAL Wr.Failure, Thread.Alerted, OSError.E); void WriteColor(FILE *wr, *c: Row3I) /* Write colors in RGB mode */ { Mis.WriteInt(wr,c[0]); fprintf(wr," "); Mis.WriteInt(wr,c[1]); fprintf(wr," "); Mis.WriteInt(wr,c[2]); } /* END WriteColor */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? cmt = "Made by SplineToWire4 on " & Today() & "\n"; ??? w4 = FileWr.Open(o->outFile & ".w4"); ??? txt = FileWr.Open(o->outFile & ".from4"); { WriteCmt(w4,o,cmt); WriteComments(txt,o,cmt); WriteWire4Header(w4); SamplePath(o,w4,txt); fclose(w4); fclose(txt); return 0; } void WriteComments(FILE *wr, *o: Options_t; cmt: char *) { int ind = 0; /* Comment indentation. */ filefmt_write_comment(wr,cmt,ind,'#'); fprintf(wr, "%*s# control points :\n", ind, ""); for (i = 0; i < o->ncp; i++) { fprintf(wr, "%s*# ", ind, ""); Mis.WritePoint(wr, o->cp[i]); fprintf(wr, "\n"); } fprintf(wr, "\n"); } /* END WriteComments */ void WriteWire4Header(wr: Wr.T) { fprintf(wr, "DegreeRing@{Edge->?}s"); fprintf(wr," 0"); fprintf(wr,"\nDepthCueLevels 10"); fprintf(wr,"\nFogDensity 0.5"); fprintf(wr,"\n"); fprintf(wr, "\nFrom4: +9 00 00 00"); fprintf(wr, "\nTo4 : 00 00 00 00"); fprintf(wr, "\nUp4 : 00 00 +1 00"); fprintf(wr, "\nOver4: 00 00 00 +1"); fprintf(wr, "\nVangle4: 30"); fprintf(wr, "\n"); fprintf(wr, "\nFrom3: +9 00 00"); fprintf(wr, "\nTo3 : 00 00 00"); fprintf(wr, "\nUp3 : 00 00 +1"); fprintf(wr, "\nVangle3: 30"); } /* END WriteWire4Header */ PROCEDURE SamplePath(*o: Options_t; w4: Wr.T; txt: Wr.T) VAR uint nv,ne; /* Number of nodes and edges in the curve spline. */ uint kv; /* Node counter */ vcolor : Row3I = Row3I{100,100,100}; ecolor : Row3I = Row3I{0,255,255}; vradius : REAL = 1.0; eradius : REAL = 1.0; { void SampleSplineArc(a, b, c, r4_t *d, np: uint) { /* To amend the first control point */ ??? tini = ((double)-2*np); ??? ta = ((double) -np); ??? tb = ((double) 0); ??? tc = ((double) np); ??? td = ((double) 2*np); ??? tfin = ((double) 3*np) DO ReportInterval(kv; with (kv+np-1); for (j = 0; j < np; j++) { ??? t = FLOAT(j, double)); with( double Q = BSplineApproximation(t, tini, ta,a, tb,b, tc,c, td,d, tfin) ){ ProcessSample(Q) } } } } SampleSplineArc; void ReportInterval(ini, fin: uint) { fprintf(stderr, "Interpoling between [ " & Fmt.Int(ini) & "-" \ Fmt.Int(fin) & "]\n"); } ReportInterval; void ProcessSample(Q: r4_t) { if (o->normalize > 0.0) { Q = r4_Scale(o->normalize, r4_Dir(r4_Sub(Q,o->To4))) }; WritePoint4DForWire4(Q,vcolor,vradius); if (kv % o->renderInterval == 0) { WritePoint4DAsText(Q,kv); }; kv++ } ProcessSample; void WriteCoord(FILE *wr, x: double) { fprintf(wr, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 4), 7)); } WriteCoord; void WritePoint4DForWire4(*c: r4_t; vcolor: Row3I; vradius: REAL) { WriteCoord(w4,c[0]); fprintf(w4, " "); WriteCoord(w4,c[1]); fprintf(w4, " "); WriteCoord(w4,c[2]); fprintf(w4, " "); WriteCoord(w4,c[3]); fprintf(w4, " : "); WriteColor(w4, vcolor); fprintf(w4, " : "); Mis.WriteRadius(w4, vradius); fprintf(w4, "\n"); } WritePoint4DForWire4; void WritePoint4DAsText(*c: r4_t; uint i) { fprintf(txt, " " & Fmt.Int(i) & " "); WriteCoord(txt,c[0]); fprintf(txt, " "); WriteCoord(txt,c[1]); fprintf(txt, " "); WriteCoord(txt,c[2]); fprintf(txt, " "); WriteCoord(txt,c[3]); fprintf(txt, "\n"); } WritePoint4DAsText; { /* compute the number of nodes */ nv = (o->ncp - 3)*o->samplesPerArc; if (o->tips) { nv = nv + 4*o->samplesPerArc + 1 } fprintf(w4, "\n\nNodeList : "); fprintf(w4, Fmt.Int(nv+5) & "\n"); kv = 0; if (o->tips) { SampleSplineArc(o->cp[0], o->cp[0], o->cp[0], o->cp[1], o->samplesPerArc); SampleSplineArc(o->cp[0], o->cp[0], o->cp[1], o->cp[2], o->samplesPerArc); } for (i = 0; i <= (o->ncp-4); i++) { SampleSplineArc(o->cp[i], o->cp[i+1], o->cp[i+2], o->cp[i+3], o->samplesPerArc); } if (o->tips) { SampleSplineArc(o->cp[o->ncp-3], o->cp[o->ncp-2], o->cp[o->ncp-1], o->cp[o->ncp-1], o->samplesPerArc); SampleSplineArc(o->cp[o->ncp-2], o->cp[o->ncp-1], o->cp[o->ncp-1], o->cp[o->ncp-1], o->samplesPerArc); ProcessSample(o->cp[o->ncp-1]) } /* reference axis nodes */ fprintf(w4, " 0 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 1 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 1 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 1 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 0 1 : 255 255 255 : 0\n"); fprintf(w4, "\n"); ne = nv - 1; fprintf(w4, "\n@{Edge->?}List " & Fmt.Int(ne+4) & ":\n"); for (i = 0; i < ne; i++) { fprintf(w4, Fmt.Pad(Fmt.Int(i), 4) & " " & Fmt.Pad(Fmt.Int(i+1),4)); fprintf(w4, " : "); /* color */ WriteColor(w4, ecolor); fprintf(w4, " : "); Mis.WriteRadius(w4, eradius); fprintf(w4, "\n"); } /* reference axis @{edge->?}s */ fprintf(w4, " " & Fmt.Int(nv) & " " & Fmt.Int(nv+1)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nv) & " " & Fmt.Int(nv+2)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nv) & " " & Fmt.Int(nv+3)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nv) & " " & Fmt.Int(nv+4)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, "\nWallList 0\n"); fclose(w4); } } /* END SamplePath */ Options_t *GetOptions(int argc, char **argv) Options_t *o = (Options_t *)malloc(sizeof(Options_t)); { argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-ncp"); o->ncp = argparser_get_next_int(pp, 4,100); o->cp = r4_vec_new(o->ncp); for (i = 0; i < o->ncp; i++) { for (j = 0; j < 4; j++) { o->cp[i,j] = pp.getNextLongReal(-100.0, 100.0); } } o->tips = argparser_keyword_present(pp, "-tips"); if ((argparser_keyword_present(pp, "-normalize"))) { o->normalize = pp.getNextLongReal(1.0d-10,1.0d+10); } else { o->normalize = 0.0; } if ((argparser_keyword_present(pp, "-samplesPerArc"))) { o->samplesPerArc = argparser_get_next_int(pp, 1,100); } else { o->samplesPerArc = 10; } if ((argparser_keyword_present(pp, "-renderInterval"))) { o->renderInterval = argparser_get_next_int(pp, 1,100); } else { o->renderInterval = 10; } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: SplineToWire4 \\\n" \ " -outFile \\\n" \ " [ -normalize ] \\\n" \ " -ncp \\\n" \ " [ ] \\\n" \ " ............................... \\\n" \ " [ ] \\\n" \ " [ -tips ] \\\n" \ " [ -samplesPerArc ] \\\n" \ " [ -renderInterval ]\n"); END¦ } } return o; } /* END GetOptions */ /* end SplineToWire4 */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Statistics.c /* This Program compute the statistics for test the influence of energy minimization (produced by OptShape). So print the average and standard desviation of length of @{edge->?}s, area of walls, volume of tetrahedra and dihedral angle between consecutives walls incidents to common @{edge->?}s. Read files (-final.tp).*/ #define Statistics_C_author \ "Created by L. P. Lozada, 1999\n" \ "Modified by L.A.P.Lozada on 99-11-23." #include // #INCLUDE // #INCLUDE #include #include #include // #INCLUDE // #INCLUDE CONST double Pi = Math.Pi; TYPE typedef struct Options_t { char *inFileTp; /* Initial guess file name (minus ".tp") */ char *inFileSt; /* Initial guess file name (minus ".tp") */ bool_t length; bool_t area; bool_t volume; bool_t angle; } TYPE double bool_vec_t = ARRAY OF bool_t; double @{Edge->?} = Triangulation.edge; double Wall = Triangulation.Wall; ??? DRF = REF uint_vec_t; VAR stl, stv, sta, std: Stat.T; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Stat.Init(stl); Stat.Init(stv); Stat.Init(sta); Stat.Init(std); Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? c = rc^; { MakeTest(o->length,o->area,o->volume,o->angle,top,c); return 0; } PROCEDURE MakeTest( bool_t length,area,volume,angle; *ElemTableRec_t *top; Coords_t *c; ) { if (length){ MakeTestLength(top,c); } if (area){ MakeTestArea(top,c); } if (volume){ MakeTestVolume(top,c); } if (angle){ MakeTestAngle(top,c); } } /* END MakeTest */ PROCEDURE MakeTestLength(ElemTableRec_t *top, Coords_t *c) { int ind = 0; /* Comment indentation. */ filefmt_write_comment(stderr, "\nThe length of @{edge->?}s\n",ind,'|'); for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; Node_t un = OrgV(e.pa)->num; Node_t vn = OrgV(Clock(e.pa))->num; ??? l = r4_Dist(c[un]; with (c[vn]), double ll = FLOAT(l, REAL) ){ fprintf(stderr, Fmt.LongReal(l) & "\n"); Stat.Accum(stl, ll); } } fprintf(stderr, "\nWeight statistics of length's @{edge->?}s :\n"); Stat.Print(stderr, stl); fprintf(stderr, "\n"); } /* END MakeTestLength */ PROCEDURE MakeTestAngle(ElemTableRec_t *top, Coords_t *c) double Angle(*f1,f2: Place_t) { ??? a = f1; ??? b = f2; Node_t ao = OrgV(a)->num; Node_t ad = OrgV(NextE(a))->num; Node_t ae = OrgV(PrevE(a))->num; Node_t bo = OrgV(b)->num; Node_t bd = OrgV(NextE(b))->num; Node_t be = OrgV(PrevE(b))->num; ??? v1a = r4_Sub(c[ad]; with (c[ao]), double v2a = r4_Sub(c[ae],c[ao]); double v1b = r4_Sub(c[bd],c[bo]); double v2b = r4_Sub(c[be],c[bo]); double p = FindOrthonormal(v1a,v2a); double q = FindOrthonormal(v1b,v2b); double cos = r4_dot(p,q) /*tethar == Math.acos(cos) /* Aproximation */*/ ){ /* assert(ao == bo) && (ad == bd); assert(0.0<=tethar) && ((tethar <= FLOAT(Pi,double))); tetha = (180.0*tethar)/((double)Pi); */ return cos; } } Angle; r4_t FindOrthonormal(*v1,v2: r4_t) { ??? u1 = v1; ??? v2_u1 = r4_Project(v2; with (u1), double u2 = r4_Sub(v2,v2_u1) DO return r4_Dir(u2); } } FindOrthonormal; Wall_vec_t *CollectWalls(*e: @{Edge->?})== uint NT = 0; VAR uint top; { int NF = top->wall.ne; ??? t = Wall_vec_new(NF)^; { for (i = 0; i < NF; i++) { top = 0; ??? f = top->wall[i]; Node_t fun = OrgV(f.pa)->num; Node_t fvn = OrgV(NextE(f.pa))->num; Node_t fwn = OrgV(PrevE(f.pa))->num; Node_t eun = OrgV(e.pa)->num; Node_t evn = OrgV(Clock(e.pa))->num; { if (((fun==eun) || (fun==evn))){ top++; } if (((fvn==eun) || (fvn==evn))){ top++; } if (((fwn==eun) || (fwn==evn))){ top++; } if (top == 2) { t[NT] = f; NT++; } } } ??? r = Wall_vec_new(NT); { r^ = SUBARRAY(t,0,NT); return r; } } } CollectWalls; VAR double dihedral; REAL dihedralr; DRF drf; @{edge->?}Relevant: REF bool_vec_t; bool_t internal; double idealcosine; { @{edge->?}Relevant = bool_vec_new(top->NE); int ind = 0; /* Comment indentation. */ filefmt_write_comment(stderr, "\nThe dihedral angles\n",ind,'|'); drf = NEW(REF uint_vec_t , top->NE); for (l = 0; l < top->NE; l++) { ??? e = top->edge[l]; ??? fie = CollectWalls(e); ??? drf = LAST(fie^)+1; { for (j = 0; j < drf; j++) { ??? f1 = fie^[j]; ??? a = f1.pa; ??? aPpos = Ppos(a); ??? aPneg = Pneg(a); { if ((aPpos!=NULL) && (aPneg!=NULL )){ internal = TRUE; } else { internal = FALSE; } } @{edge->?}Relevant[l] = TRUE) && (internal; }; if (@{edge->?}Relevant[l] ){ fprintf(stderr, " -corresponding to @{edge->?}: " \ Fmt.Int(l) & "\n"); for (j = 0; j < drf; j++) { ??? f1 = fie^[j]; ??? a = f1.pa; Place_t b = NextF(a); { dihedral = Angle(a,b); fprintf(stderr, Fmt.LongReal(dihedral) & "\n"); dihedralr = FLOAT(dihedral, REAL); Stat.Accum(std,dihedralr); } } idealcosine=cos((2.0*FLOAT(Pi,double))/FLOAT(drf,double)); } } } fprintf(stderr, "\nWeight statistics of dihedral angles:\n"); Stat.Print(stderr, std); fprintf(stderr, "\n"); fprintf(stderr,"Ideal Cosine " & Fmt.LongReal(idealcosine) & "\n"); } /* END MakeTestAngle */ PROCEDURE MakeTestVolume(ElemTableRec_t *top, Coords_t *c) { int ind = 0; /* Comment indentation. */ filefmt_write_comment(stderr, "\nThe volume of tetrahedrons\n",ind,'|'); for (i = 0; i < top->cell.ne; i++) { ??? vt = TetrahedronNodes(Srot(top.cell[i])); ??? un = vt[0]; ??? vn = vt[1]; ??? wn = vt[2]; ??? xn = vt[3]; ??? uv = r4_Sub(c[vn]; with (c[un]), double uw = r4_Sub(c[wn],c[un]); double ux = r4_Sub(c[xn],c[un]); double n = r4_cross(uv, uw, ux); double v = 1.0/6.0 * r4_Norm(n); double vv = FLOAT(v, REAL) ){ fprintf(stderr, Fmt.LongReal(v) & "\n"); Stat.Accum(stv, vv); } } fprintf(stderr, "\nWeight statistics of volume's cell:\n"); Stat.Print(stderr, stv); fprintf(stderr, "\n"); } /* END MakeTestVolume */ PROCEDURE TetrahedronNodes(f:TriangulationPlace_t): ARRAY [0..3] OF uint == /* Was exchange OrgV by Org for considering the dual space. */ { Place_t g = Tors(f); Place_t h = Tors(Clock(PrevE(f))); ??? p = Org(g)->num; ??? q = Org(NextE(g))->num; ??? r = Org(PrevE(g))->num; ??? s = Org(PrevE(h))->num; { return ARRAY [0..3] OF uint {p, q, r, s}; } } /* END TetrahedronNodes */ PROCEDURE MakeTestArea(ElemTableRec_t *top, Coords_t *c) { int ind = 0; /* Comment indentation. */ filefmt_write_comment(stderr, "\nThe area of triangles\n",ind,'|'); for (i = 0; i < top->wall.ne; i++) { ??? p = top->wall[i]; Node_t un = OrgV(p.pa)->num; Node_t vn = OrgV(NextE(p.pa))->num; Node_t wn = OrgV(PrevE(p.pa))->num; ??? a = r4_Dist(c[vn]; with (c[un]), double b = r4_Dist(c[wn],c[un]); double c = r4_Dist(c[vn],c[wn]); double p = (a+b+c); double s = 0.5 * p; double sa = s - a; double sb = s - b; double sc = s - c; double ar = sqrt(s*sa*sb*sc); double arr = FLOAT(ar, REAL) ){ fprintf(stderr, Fmt.LongReal(ar) & "\n"); Stat.Accum(sta, arr); } } fprintf(stderr, "\nWeight statistics of area's walls:\n"); Stat.Print(stderr, sta); fprintf(stderr, "\n"); } /* END MakeTestArea */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); o->length = argparser_keyword_present(pp, "-length"); o->area = argparser_keyword_present(pp, "-area"); o->volume = argparser_keyword_present(pp, "-volume"); o->angle = argparser_keyword_present(pp, "-angle"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Statistics \\\n" \ " -inFileTp \\\n" \ " -inFileSt \\\n" \ " [ -length ] [ -volume ] [ -area ]" \ " [ -angle ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } Statistics. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/SubGon.c #define PROG_NAME "SubGon" #define PROG_DESC "???" #define PROG_VERS "1.0" #define SubGon_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program receives as input a single cell (the envelope) and produces a include file with the barycentric subdivision of walls (2-skeleton) and cells (3-skeleton) but in an exploding way. */ #define SubGon_C_author \ "Modified by L.A.P.Lozada on 2000-05-19." // #INCLUDE #include // #INCLUDE // #INCLUDE #include TYPE typedef struct Options_t { uint order; /* order of the triangle star */ char *outFile; /* Output file name prefix */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) REF Place_vec_t a ; { ElemTableRec_t top; Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ { Place_vec_t a = Place_vec_new(o->order); for (i = 0; i < o->order; i++) { a[i] = Squared.MakeTriangle(); } for (i = 0; i < o->order; i++) { SetNextF(NextE(a[i]), Clock(PrevE(a[(i+1) % o->order]))); SetRingEdgeInfo(NextE(a[i]), PEdge(NextE(a[i]))); } for (i = 0; i < o->order; i++) { SetOrgAll(NextE(a[i]), OrgV(NextE(a[i]))); SetOrgAll(PrevE(a[i]), OrgV(PrevE(a[i]))); SetOrgAll(a[i], OrgV(a[i])); } top = MakeElemTable(a[0]); ??? c = GenCoords(top); { WriteTopology(o->outFile, top, "Created by SubGon: gon-" \ Fmt.Int(o->order) & ".tp"); WriteState(o->outFile, top, c^, "Created by SubGon: gon-" & Fmt.Int(o->order) & ".st"); WriteMaterials(o->outFile, top,"Created by SubGon: gon-" \ Fmt.Int(o->order) & ".ma"); } } } DoIt; Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-order"); o->order = argparser_get_next_int(pp, 2,20); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: SubGon \\\n" \ " -order \\\n" \ " -outFile \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } SubGon. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestCorner.c #define PROG_NAME "TestCorner" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestCorner_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Test the corners for one topological tetrahedron. */ // #INCLUDE /* [!!! Used to include instead of !!! ] */ #include // #INCLUDE // #INCLUDE // #INCLUDE // Clock, Spin, Srot, Tors; // #INCLUDE // Corner, CCorner; TYPE double Place_t = Octf_Place_t; VAR Place_t ca.e[8]; PROCEDURE PrintCorner() { for (l = 1; l < 5; l++) { ??? a = Octf.MakeWedge(); ??? b = Mapi.MakeWedge(l); ??? fes = NARROW(PWedge(b)-> with ( Mapi.wedge), double fet = PWedge(a) ){ fet.order = fes.order; fet.ca = fes.ca; /* Octf.PrintPlacenl(stderr, a, 1); fprintf(stderr, "\n"); */ fprintf(stderr, "(" & Fmt.Int(l) & "," & Fmt.Int(l) & "):" & "\n"); fprintf(stderr, "Corner(a)== "); Octf.PrintPlacenl(stderr, Corner(a), 1); fprintf(stderr, "CornerSpin(a)== "); Octf.PrintPlacenl(stderr, Corner(Spin(a)), 1); fprintf(stderr, "CornerSrot(a)== "); Octf.PrintPlacenl(stderr, Corner(Srot(a)), 1); fprintf(stderr, "CornerSpinSrot(a)== "); Octf.PrintPlacenl(stderr, Corner(Spin(Srot(a))), 1); fprintf(stderr, "CornerClock(a)== "); Octf.PrintPlacenl(stderr, Corner(Clock(a)), 1); fprintf(stderr, "CornerSpinClock(a)== "); Octf.PrintPlacenl(stderr, Corner(Spin(Clock(a))), 1); fprintf(stderr, "CornerTor(a)== "); Octf.PrintPlacenl(stderr, Corner(Tors(a)), 1); fprintf(stderr, "CornerSpinTors(a)== "); Octf.PrintPlacenl(stderr, Corner(Spin(Tors(a))), 1); } } } PrintCorner; PROCEDURE PrintCCorner() { for (l = 1; l < 5; l++) { ??? a = Octf.MakeWedge(); ??? b = Mapi.MakeWedge(l); ??? fes = NARROW(PWedge(b)-> with ( Mapi.wedge), double fet = PWedge(a) ){ fet.order = fes.order; fet.ca = fes.ca; fprintf(stderr, "CCorner(a)== "); Octf.PrintPlacenl(stderr, CCorner(a), 1); fprintf(stderr, "CCornerSpin(a)== "); Octf.PrintPlacenl(stderr, CCorner(Spin(a)), 1); fprintf(stderr, "CCornerSrot(a)== "); Octf.PrintPlacenl(stderr, CCorner(Srot(a)), 1); fprintf(stderr, "CCornerSpinSrot(a)== "); Octf.PrintPlacenl(stderr, CCorner(Spin(Srot(a))), 1); fprintf(stderr, "CCornerClock(a)== "); Octf.PrintPlacenl(stderr, CCorner(Clock(a)), 1); fprintf(stderr, "CCornerSpinClock(a)== "); Octf.PrintPlacenl(stderr, CCorner(Spin(Clock(a))), 1); fprintf(stderr, "CCornerTors(a)== "); Octf.PrintPlacenl(stderr, CCorner(Tors(a)), 1); fprintf(stderr, "CCornerSpinTors(a)== "); Octf.PrintPlacenl(stderr, CCorner(Spin(Tors(a))), 1); } } } PrintCCorner; void Teste() { for (i = 1; i < 5; i++){ ca = MakeTetraTopo(i,i); fprintf(stderr, "(" & Fmt.Int(i) & "," & Fmt.Int(i) & "):" & "\n"); for (k = 0; k < 8; k++) { fprintf(stderr, "c[" & Fmt.Int(k) & "]== "); Octf.PrintPlacenl(stderr, ca.e[k],3); } } } Teste; { PrintCorner(); PrintCCorner(); Teste(); } TestCorner. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ /**************************************************************************** (1,1): Corne r(a)8:2:1 CornerSpi n(a)5:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)9:0:1 CornerCloc k(a)5:0:1 CornerSpinCloc k(a)8:0:0 CornerTo r(a)9:2:0 CornerSpinTor s(a)0:2:1 (2,2): Corne r(a)17:2:1 CornerSpi n(a)8:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)27:0:1 CornerCloc k(a)23:0:1 CornerSpinCloc k(a)32:0:0 CornerTo r(a)33:2:0 CornerSpinTor s(a)3:2:1 (3,3): Corne r(a)26:2:1 CornerSpi n(a)11:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)57:0:1 CornerCloc k(a)53:0:1 CornerSpinCloc k(a)68:0:0 CornerTo r(a)69:2:0 CornerSpinTor s(a)6:2:1 (4,4): Corne r(a)35:2:1 CornerSpi n(a)14:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)99:0:1 CornerCloc k(a)95:0:1 CornerSpinCloc k(a)116:0:0 CornerTo r(a)117:2:0 CornerSpinTor s(a)9:2:1 (1,1): CCorne r(a)5:2:1 CCornerSpi n(a)8:2:0 CCornerSro t(a)9:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)8:0:1 CCornerSpinCloc k(a)5:0:0 CCornerTor s(a)0:2:0 CCornerSpinTor s(a)9:2:1 (2,2): CCorne r(a)8:2:1 CCornerSpi n(a)17:2:0 CCornerSro t(a)27:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)32:0:1 CCornerSpinCloc k(a)23:0:0 CCornerTor s(a)3:2:0 CCornerSpinTor s(a)33:2:1 (3,3): CCorne r(a)11:2:1 CCornerSpi n(a)26:2:0 CCornerSro t(a)57:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)68:0:1 CCornerSpinCloc k(a)53:0:0 CCornerTor s(a)6:2:0 CCornerSpinTor s(a)69:2:1 (4,4): CCorne r(a)14:2:1 CCornerSpi n(a)35:2:0 CCornerSro t(a)99:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)116:0:1 CCornerSpinCloc k(a)95:0:0 CCornerTor s(a)9:2:0 CCornerSpinTor s(a)117:2:1 (1,1): c[0]== 8:2:1 c[1]== 5:2:0 c[2]== 0:0:0 c[3]== 9:0:1 c[4]== 5:0:1 c[5]== 8:0:0 c[6]== 9:2:0 c[7]== 0:2:1 (2,2): c[0]== 17:2:1 c[1]== 8:2:0 c[2]== 0:0:0 c[3]== 27:0:1 c[4]== 23:0:1 c[5]== 32:0:0 c[6]== 33:2:0 c[7]== 3:2:1 (3,3): c[0]== 26:2:1 c[1]== 11:2:0 c[2]== 0:0:0 c[3]== 57:0:1 c[4]== 53:0:1 c[5]== 68:0:0 c[6]== 69:2:0 c[7]== 6:2:1 (4,4): c[0]== 35:2:1 c[1]== 14:2:0 c[2]== 0:0:0 c[3]== 99:0:1 c[4]== 95:0:1 c[5]== 116:0:0 c[6]== 117:2:0 c[7]== 9:2:1 ***************************************************************************/ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestCornerFE.c #define PROG_NAME "TestCornerFE" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestCornerFE_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE // Clock, Spin, Srot, Tors; // #INCLUDE // Corner, CCorner; TYPE double Place_t = Octf_Place_t; VAR Place_t ca.e[8]; PROCEDURE PrintCorner() { for (l = 1; l < 5; l++) { ??? a = Map.MakeWedge(l); { /* Octf.PrintPlace(stderr, a, 1); fprintf(stderr, "\n"); */ fprintf(stderr, "(" & Fmt.Int(l) & "," & Fmt.Int(l) & "):" & "\n"); fprintf(stderr, "Corner(a)== "); Octf.PrintPlace(stderr, Corner(a), 1); fprintf(stderr, "CornerSpin(a)== "); Octf.PrintPlace(stderr, Corner(Spin(a)), 1); fprintf(stderr, "CornerSrot(a)== "); Octf.PrintPlace(stderr, Corner(Srot(a)), 1); fprintf(stderr, "CornerSpinSrot(a)== "); Octf.PrintPlace(stderr, Corner(Spin(Srot(a))), 1); fprintf(stderr, "CornerClock(a)== "); Octf.PrintPlace(stderr, Corner(Clock(a)), 1); fprintf(stderr, "CornerSpinClock(a)== "); Octf.PrintPlace(stderr, Corner(Spin(Clock(a))), 1); fprintf(stderr, "CornerTor(a)== "); Octf.PrintPlace(stderr, Corner(Tors(a)), 1); fprintf(stderr, "CornerSpinTors(a)== "); Octf.PrintPlace(stderr, Corner(Spin(Tors(a))), 1); } } } PrintCorner; PROCEDURE PrintCCorner() { for (l = 1; l < 5; l++) { ??? a = Map.MakeWedge(l); { fprintf(stderr, "(" & Fmt.Int(l) & "," & Fmt.Int(l) & "):" & "\n"); fprintf(stderr, "CCorner(a)== "); Octf.PrintPlace(stderr, CCorner(a), 1); fprintf(stderr, "CCornerSpin(a)== "); Octf.PrintPlace(stderr, CCorner(Spin(a)), 1); fprintf(stderr, "CCornerSrot(a)== "); Octf.PrintPlace(stderr, CCorner(Srot(a)), 1); fprintf(stderr, "CCornerSpinSrot(a)== "); Octf.PrintPlace(stderr, CCorner(Spin(Srot(a))), 1); fprintf(stderr, "CCornerClock(a)== "); Octf.PrintPlace(stderr, CCorner(Clock(a)), 1); fprintf(stderr, "CCornerSpinClock(a)== "); Octf.PrintPlace(stderr, CCorner(Spin(Clock(a))), 1); fprintf(stderr, "CCornerTors(a)== "); Octf.PrintPlace(stderr, CCorner(Tors(a)), 1); fprintf(stderr, "CCornerSpinTors(a)== "); Octf.PrintPlace(stderr, CCorner(Spin(Tors(a))), 1); } } } PrintCCorner; void Teste() { for (i = 1; i < 5; i++){ ca = MakeTetraTopo(i,i); fprintf(stderr, "(" & Fmt.Int(i) & "," & Fmt.Int(i) & "):" & "\n"); for (k = 0; k < 8; k++) { fprintf(stderr, "c[" & Fmt.Int(k) & "]== "); Octf.PrintPlace(stderr, ca.e[k],3); } } } Teste; { PrintCorner(); PrintCCorner(); Teste(); } TestCorner. /**************************************************************************** (1,1): Corne r(a)8:2:1 CornerSpi n(a)5:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)9:0:1 CornerCloc k(a)5:0:1 CornerSpinCloc k(a)8:0:0 CornerTo r(a)9:2:0 CornerSpinTor s(a)0:2:1 (2,2): Corne r(a)17:2:1 CornerSpi n(a)8:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)27:0:1 CornerCloc k(a)23:0:1 CornerSpinCloc k(a)32:0:0 CornerTo r(a)33:2:0 CornerSpinTor s(a)3:2:1 (3,3): Corne r(a)26:2:1 CornerSpi n(a)11:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)57:0:1 CornerCloc k(a)53:0:1 CornerSpinCloc k(a)68:0:0 CornerTo r(a)69:2:0 CornerSpinTor s(a)6:2:1 (4,4): Corne r(a)35:2:1 CornerSpi n(a)14:2:0 CornerSro t(a)0:0:0 CornerSpinSro t(a)99:0:1 CornerCloc k(a)95:0:1 CornerSpinCloc k(a)116:0:0 CornerTo r(a)117:2:0 CornerSpinTor s(a)9:2:1 (1,1): CCorne r(a)5:2:1 CCornerSpi n(a)8:2:0 CCornerSro t(a)9:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)8:0:1 CCornerSpinCloc k(a)5:0:0 CCornerTor s(a)0:2:0 CCornerSpinTor s(a)9:2:1 (2,2): CCorne r(a)8:2:1 CCornerSpi n(a)17:2:0 CCornerSro t(a)27:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)32:0:1 CCornerSpinCloc k(a)23:0:0 CCornerTor s(a)3:2:0 CCornerSpinTor s(a)33:2:1 (3,3): CCorne r(a)11:2:1 CCornerSpi n(a)26:2:0 CCornerSro t(a)57:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)68:0:1 CCornerSpinCloc k(a)53:0:0 CCornerTor s(a)6:2:0 CCornerSpinTor s(a)69:2:1 (4,4): CCorne r(a)14:2:1 CCornerSpi n(a)35:2:0 CCornerSro t(a)99:0:0 CCornerSpinSro t(a)0:0:1 CCornerCloc k(a)116:0:1 CCornerSpinCloc k(a)95:0:0 CCornerTor s(a)9:2:0 CCornerSpinTor s(a)117:2:1 (1,1): c[0]== 8:2:1 c[1]== 5:2:0 c[2]== 0:0:0 c[3]== 9:0:1 c[4]== 5:0:1 c[5]== 8:0:0 c[6]== 9:2:0 c[7]== 0:2:1 (2,2): c[0]== 17:2:1 c[1]== 8:2:0 c[2]== 0:0:0 c[3]== 27:0:1 c[4]== 23:0:1 c[5]== 32:0:0 c[6]== 33:2:0 c[7]== 3:2:1 (3,3): c[0]== 26:2:1 c[1]== 11:2:0 c[2]== 0:0:0 c[3]== 57:0:1 c[4]== 53:0:1 c[5]== 68:0:0 c[6]== 69:2:0 c[7]== 6:2:1 (4,4): c[0]== 35:2:1 c[1]== 14:2:0 c[2]== 0:0:0 c[3]== 99:0:1 c[4]== 95:0:1 c[5]== 116:0:0 c[6]== 117:2:0 c[7]== 9:2:1 ***************************************************************************/ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestCornerQE.c #define PROG_NAME "TestCornerQE" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestCornerQE_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " // #INCLUDE #include // #INCLUDE // #INCLUDE // #INCLUDE // Splice, S, ONext, OPrev, Flip, Tor, Rot; // #INCLUDE // Org; // #INCLUDE // Corner, CCorner, Middle; TYPE double Arc = Oct.Arc; double Count = Triang.Count; double AdjacencyMatrix = Triang.AdjacencyMatrix; VAR Arc ca.e[7+1]; PROCEDURE PrintCorner() { for (l = 1; l < 5; l++) { ??? a = Map.Make@{Edge->?}(l); { /* Oct.PrintArc(Stdio.stderr, a); fprintf(stderr, "\n"); */ fprintf(stderr, "(" & Fmt.Int(l) & "," & Fmt.Int(l) & "):" & "\n"); fprintf(stderr, "Corner(a)== "); Oct.PrintArc(stderr, Corner(a)); fprintf(stderr, "CornerFlip(a)== "); Oct.PrintArc(stderr, Corner(Flip(a))); fprintf(stderr, "CornerRot(a)== "); Oct.PrintArc(stderr, Corner(Rot(a))); fprintf(stderr, "CornerFlipRot(a)== "); Oct.PrintArc(stderr, Corner(Flip(Rot(a)))); fprintf(stderr, "CornerSym(a)== "); Oct.PrintArc(stderr, Corner(Sym(a))); fprintf(stderr, "CornerFlipSym(a)== "); Oct.PrintArc(stderr, Corner(Flip(Sym(a)))); fprintf(stderr, "CornerTor(a)== "); Oct.PrintArc(stderr, Corner(Tor(a))); fprintf(stderr, "CornerFlipTor(a)== "); Oct.PrintArc(stderr, Corner(Flip(Tor(a)))); } } } PrintCorner; PROCEDURE PrintCCorner() { for (l = 1; l < 5; l++) { ??? a = Map.Make@{Edge->?}(l); { fprintf(stderr, "(" & Fmt.Int(l) & "," & Fmt.Int(l) & "):" & "\n"); fprintf(stderr, "CCorner(a)== "); Oct.PrintArc(stderr, CCorner(a)); fprintf(stderr, "CCornerFlip(a)== "); Oct.PrintArc(stderr, CCorner(Flip(a))); fprintf(stderr, "CCornerRot(a)== "); Oct.PrintArc(stderr, CCorner(Rot(a))); fprintf(stderr, "CCornerFlipRot(a)== "); Oct.PrintArc(stderr, CCorner(Flip(Rot(a)))); fprintf(stderr, "CCornerSym(a)== "); Oct.PrintArc(stderr, CCorner(Sym(a))); fprintf(stderr, "CCornerFlipSym(a)== "); Oct.PrintArc(stderr, CCorner(Flip(Sym(a)))); fprintf(stderr, "CCornerTor(a)== "); Oct.PrintArc(stderr, CCorner(Tor(a))); fprintf(stderr, "CCornerFlipTor(a)== "); Oct.PrintArc(stderr, CCorner(Flip(Tor(a)))); } } } PrintCCorner; void Teste() VAR Arc ca.e[7+1]; Arc middle,c; ElemTableRec_t *top; /* Was {t} */; @{edge->?} : REF ARRAY OF Arc; NE : uint = 0; { ??? a = Map.Make@{Edge->?}(2); { /* for (l = 4; l < 5; l++) { ca = Triang.MakeGrid(l,l); for (k = 0; k < 8; k++) { fprintf(stderr, "c[" & Fmt.Int(k) & "]== "); Oct.PrintArc(Stdio.stderr, ca.e[k]); fprintf(stderr, "\n"); } */ top = Triang.MakeElemTable(a); for (k = 0; k < 8; k++) { fprintf(stderr, "c[" & Fmt.Int(k) & "]== "); Oct.PrintArc(Stdio.stderr, ca.e[k]); fprintf(stderr, "\n"); } } } Teste; { /* PrintCorner(); PrintCCorner(); PrintMiddle(); Teste(); */ MakeTorus(); } testeCantos. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestCurvature.c #define PROG_NAME "TestCurvature" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestCurvature_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This module generates two symetric random variations of a given ".st" file, for submit to the TestEnergy procedure. */ #include // #INCLUDE #include // #INCLUDE #include #include // // #INCLUDE TYPE typedef struct Options_t { char *inFileTp; /* Input file name (topology) */ char *inFileSt; /* Input file name (state) */ char *output; /* Output file name prefix */ char *magnitude; /* for indicate how constructs the random conf. */ REAL jitter; /* Magnitude of random perturbation */ bool_t normalize; /* TRUE to normalize the node coordinates */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? coins = NEW(Random.Default).init(TRUE); ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? cOld = rc^; ??? cNew = NEW(REF Coords_t; with ( top->node.ne)^, double cmt = " Random variation : " & o->magnitude & "\n" \ " Randomizing from: " & o->inFileSt & ".st\n" & " Created by TestCurvature: " & o->output & ".st\n" ){ if (o->normalize) { Triangulation.NormalizeNodeDistance(top, cOld) } cNew = cOld; PerturbCoords(top, cNew, coins, ((double)o->jitter), o->magnitude); if (o->normalize) { Triangulation.NormalizeNodeDistance(top, cNew) } WriteState(o->output, top, cNew,cmt); return 0; } PROCEDURE PerturbCoords(ElemTableRec_t *top, Coords_t *c, rand_t *coins; double jitter; char *magnitude; ) { for (i = 0 TO (c.ne-1)){ if ((OrgV(top->node.e[i])->exists) && (NOT top->node[i].fixed)) { ??? ci = c[i]; with ( double p = (r4_t) { jitter * coins.longreal(-1.0, +1.0), jitter * coins.longreal(-1.0, +1.0), jitter * coins.longreal(-1.0, +1.0), jitter * coins.longreal(-1.0, +1.0) } ){ if (0 == strcmp(magnitude,"+"))) { ci = r4_Add(ci, p); } else { ci = r4_Sub(ci, p); } } } } } /* END PerturbCoords */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); argparser_get_keyword(pp, "-output"); o->output = argparser_get_next(pp); argparser_get_keyword(pp, "-magnitude"); o->magnitude = argparser_get_next(pp); o->normalize = argparser_keyword_present(pp, "-normalize"); if ((argparser_keyword_present(pp, "-jitter"))) { o->jitter = pp.getNextReal(0.0); } else { o->jitter = 1.0 } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestCurvature \\\n" \ " -inFileTp -inFileSt \\\n" \ " -output -magnitude < + | - > \\\n" \ " [ -normalize ] [ -jitter ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestCurvature. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestElasticity.c #define PROG_NAME "TestElasticity" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestElasticity_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " #include #include // #INCLUDE #include #include #include CONST double A = LR3x3.T { (r3_t){0.0, 1.0, 1.0}, (r3_t){1.0, 0.0, 1.0}, (r3_t){1.0, 1.0, 0.0} } double B = LR4x4.T { (r4_t){0.0, 0.0, 0.0, 1.0}, (r4_t){0.0, 1.0, 1.0, 1.0}, (r4_t){1.0, 1.0, 0.0, 1.0}, (r4_t){1.0, 0.0, 1.0, 1.0} } TYPE double LR4x3 = ARRAY [0..3] OF r3_t; double LR3x4 = ARRAY [0..2] OF r4_t; LR4x3 Transpose_3x4(*m: LR3x4) /* Return the transpose of a matrix 3x4. */ t : LR4x3; { t[0] = (r3_t){m[0,0], m[1,0], m[2,0]}; t[1] = (r3_t){m[0,1], m[1,1], m[2,1]}; t[2] = (r3_t){m[0,2], m[1,2], m[2,2]}; t[3] = (r3_t){m[0,3], m[1,3], m[2,3]}; return t; } /* END Transpose_3x4 */ LR3x4 Transpose_4x3(*m: LR4x3) /* return the transpose of a matrix 3x3. */ t : LR3x4; { t[0] = (r4_t){m[0,0], m[1,0], m[2,0], m[3,0]}; t[1] = (r4_t){m[0,1], m[1,1], m[2,1], m[3,1]}; t[2] = (r4_t){m[0,2], m[1,2], m[2,2], m[3,2]}; return t; } /* END Transpose_4x3 */ LR4x3 Mul_4x3_3x3(*a: LR4x3; *b: LR3x3.T) /* Return the product of the matrix "a" 4x3 and matrix "b" 3x3. */ c : LR4x3; { ??? a00 = a[0; with (0], a01 == a[0,1], a02 == a[0,2], double a10 = a[1,0], a11 == a[1,1], a12 == a[1,2]; double a20 = a[2,0], a21 == a[2,1], a22 == a[2,2]; double a30 = a[3,0], a31 == a[3,1], a32 == a[3,2]; double b00 = b[0,0], b01 == b[0,1], b02 == b[0,2]; double b10 = b[1,0], b11 == b[1,1], b12 == b[1,2]; double b20 = b[2,0], b21 == b[2,1], b22 == b[2,2]; double c00 = a00 * b00 + a01 * b10 + a02 * b20; double c01 = a00 * b01 + a01 * b11 + a02 * b21; double c02 = a00 * b02 + a01 * b12 + a02 * b22; double c10 = a10 * b00 + a11 * b10 + a12 * b20; double c11 = a10 * b01 + a11 * b11 + a12 * b21; double c12 = a10 * b02 + a11 * b12 + a12 * b22; double c20 = a20 * b00 + a21 * b10 + a22 * b20; double c21 = a20 * b01 + a21 * b11 + a22 * b21; double c22 = a20 * b02 + a21 * b12 + a22 * b22; double c30 = a30 * b00 + a31 * b10 + a32 * b20; double c31 = a30 * b01 + a31 * b11 + a32 * b21; double c32 = a30 * b02 + a31 * b12 + a32 * b22; double c0 = (r3_t){c00,c01,c02}; double c1 = (r3_t){c10,c11,c12}; double c2 = (r3_t){c20,c21,c22}; double c3 = (r3_t){c30,c31,c32} ){ c[0] = c0; c[1] = c1; c[2] = c2; c[3] = c3; return c; } } /* END Mul_4x3_3x3 */ LR3x3.T Mul_3x4_4x3(*a: LR3x4; *b: LR4x3) /* Return the product of the matrix "a" 3x4 and matrix "b" 4x3. */ { ??? a00 = a[0; with (0], a01 == a[0,1], a02 == a[0,2], a03 == a[0,3], double a10 = a[1,0], a11 == a[1,1], a12 == a[1,2], a13 == a[1,3]; double a20 = a[2,0], a21 == a[2,1], a22 == a[2,2], a23 == a[2,3]; double b00 = b[0,0], b01 == b[0,1], b02 == b[0,2]; double b10 = b[1,0], b11 == b[1,1], b12 == b[1,2]; double b20 = b[2,0], b21 == b[2,1], b22 == b[2,2]; double b30 = b[3,0], b31 == b[3,1], b32 == b[3,2]; double c00 = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30; double c01 = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31; double c02 = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32; double c10 = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30; double c11 = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31; double c12 = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32; double c20 = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30; double c21 = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31; double c22 = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32; double c0 = (r3_t){c00,c01,c02}; double c1 = (r3_t){c10,c11,c12}; double c2 = (r3_t){c20,c21,c22} ){ return LR3x3.T{c0,c1,c2}; } } /* END Mul_3x4_4x3 */ PROCEDURE PrintMatrix_3x3(*a: LR3x3.T) { for (i = 0; i < 3; i++){ for (j = 0; j < 3; j++) { Mis.WriteLong(stderr, a[i,j]); fprintf(stderr, " "); } fprintf(stderr, "\n"); } } /* END PrintMatrix_3x3 */ PROCEDURE PrintMatrix_3x4(*a: LR3x4) { for (i = 0; i < 3; i++){ for (j = 0; j < 4; j++) { Mis.WriteLong(stderr, a[i,j]); fprintf(stderr, " "); } fprintf(stderr, "\n"); } } /* END PrintMatrix_3x4 */ PROCEDURE PrintMatrix_4x3(*a: LR4x3) { for (i = 0; i < 4; i++){ for (j = 0; j < 3; j++) { Mis.WriteLong(stderr, a[i,j]); fprintf(stderr, " "); } fprintf(stderr, "\n"); } } /* END PrintMatrix_4x3 */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) B : LR4x3; { with ( double b0 = (r3_t){10.0, 10.0, 10.0}; double b1 = (r3_t){10.0, 10.0, 10.0}; double b2 = (r3_t){10.0, 10.0, 10.0}; double b3 = (r3_t){10.0, 10.0, 10.0} ){ B[0] = b0; B[1] = b1; B[2] = b2; B[3] = b3; fprintf(stderr, "\nMatrix A\n"); PrintMatrix_3x3(A); fprintf(stderr, "\nMatrix B\n"); PrintMatrix_4x3(B); fprintf(stderr, "\nMatrix A_1\n"); PrintMatrix_3x3(LR3x3.Inv(A)); fprintf(stderr, "\nMatrix A* A_1\n"); PrintMatrix_3x3(LR3x3.Mul(A,LR3x3.Inv(A))); /* fprintf(stderr, "\nMatrix B'\n"); PrintMatrix_3x4(Transpose_4x3(B)); fprintf(stderr, "\nMatrix B''\n"); PrintMatrix_4x3(Transpose_3x4(Transpose_4x3(B))); fprintf(stderr, "\nMatrix BxA\n"); PrintMatrix_4x3(Mul_4x3_3x3(B,A)); fprintf(stderr, "\nMatrix B'xB\n"); PrintMatrix_3x3(Mul_3x4_4x3(Transpose_4x3(B),B)); */ fprintf(stderr, "\nMatrix BxA_1\n"); PrintMatrix_4x3(Mul_4x3_3x3(B,LR3x3.Inv(A))); return 0; } { DoIt(); fprintf(stderr, "volume :" & Fmt.LongReal(1.0/6.0*LR3x3.Det(A)) \ "\n"); } TestElasticity. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ /* Testes Matrix A 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 Matrix B 1.00 0.00 0.00 0.00 2.00 0.00 0.00 0.00 3.00 1.00 1.00 1.00 Matrix B' 1.00 0.00 0.00 1.00 0.00 2.00 0.00 1.00 0.00 0.00 3.00 1.00 Matrix B'' 1.00 0.00 0.00 0.00 2.00 0.00 0.00 0.00 3.00 1.00 1.00 1.00 Matrix BxA 1.00 0.00 0.00 0.00 2.00 0.00 0.00 0.00 3.00 1.00 1.00 1.00 Matrix B'xB 2.00 1.00 1.00 1.00 5.00 1.00 1.00 1.00 10.00 */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestEnergy.c #define PROG_NAME "TestEnergy" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestEnergy_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Tests an energy function. Takes as input two ".st" files with same topology but different coordinate vectors, and evaluates a given energy function for all configurations that interpolate between the two, at "nSteps" equal intervals. The output is a ".plot" file that can be examined with "gnuplot". Optionally, the program writes the ".st" file with minimum energy. */ // #INCLUDE // #INCLUDE // #INCLUDE #include #include #include // #INCLUDE // Coords_t; TYPE double bool_vec_t = ARRAY OF bool_t; TYPE typedef struct Options_t { char *tpFile; /* Topology file (minus ".tp") */ char *aFile, bFile; /* Configuration files (minus ".st") */ char *outFile; /* Output file names (minus ".plot"/".st") */ eFunction: MixedEnergy.T; /* Energy function */ uint nSteps; /* Number of steps to take */ bool_t showMin; /* TRUE to write interpolated ".st" files */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); double eMin = (double.ne-1); double sMin; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tpData = Triangulation.ReadToMa(o->tpFile); ??? top = tpData.top; ??? ac = Triangulation.ReadState(o->aFile)^; ??? bc = Triangulation.ReadState(o->bFile)^; ??? NV = top->node.ne; ??? c = r4_vec_new(top->node.ne)^; ??? cDs = r4_vec_new(top->node.ne)^; ??? eDc = r4_vec_new(top->node.ne)^; ??? vTot = bool_vec_new(top->node.ne)^; ??? vSome = bool_vec_new(top->node.ne)^; ??? pwr = FileWr.Open(o->outFile & ".plot"); { assert((ac.ne) == NV); assert((bc.ne) == NV); WriteHeader(pwr); o->eFunction.defTop(top); Triangulation.GetVariableNodes(top, vTot); for (i = 0; i < NV; i++) { cDs[i] = r4_Sub(bc[i], ac[i]); vSome[i] = r4_Norm(cDs[i])!=0.0 } GradTest("initial", o->eFunction, ac, vTot, eDc); GradTest("final", o->eFunction, bc, vTot, eDc); for (i = 0; i <= (o->nSteps); i++) { ??? s = ((double)i)/((double)o->nSteps); { fprintf(pwr, " "); fprintf(pwr, " " & FLR(s, 6, 4)); /* Define coordinates */ for (i = 0; i < top->node.ne; i++) { c[i] = r4_Mix(1.0 - s, ac[i], s, bc[i]) } /* Evaluate with all or only some nodes variable: */ ??? eTot = EvalTest(pwr; with (o->eFunction, c, cDs, vTot, eDc), double eSome = EvalTest(pwr, o->eFunction, c, cDs, vSome, eDc) ){ /* Compare: */ fprintf(pwr, " "); fprintf(pwr, " " & ELR(eTot-eSome, 15, 8)); if (eTot < eMin) { eMin = eTot; sMin = s } } fprintf(pwr, "\n"); fflush(pwr); } } fclose(pwr); if (o->showMin) { ??? name = o->outFile & "-min"; ??? cmt = " Topology file == " & o->tpFile & "\n" \ " Configuration files: " & o->aFile & "; with (\n " & o->bFile & "\n" \ " Energy function to test: " & o->eFunction.name() & "\n" \ " Minimum energy: " & FLR(eMin, 16, 8) & "\n" \ " Position of minimum: " & Fmt.LongReal(sMin) DO for (i = 0; i < NV; i++) { c[i] = r4_Mix(1.0 - sMin, ac[i], sMin, bc[i]) } WriteState(name, top, c, cmt) } } return 0; } PROCEDURE GradTest( char *cfgName; /* Configuration name. */ eFunction: MixedEnergy.T; /* Energy function. */ Coords_t *c; /* Node coordinates. */ bool_vec_t *v; /* Mutable nodes. */ Coords_t *eDc; /* Work area for gradient. */ ) double e, ep, cOld; eDcNum: r4_t; CONST DiffStep == 0.0001; { fprintf(stderr, "Gradient test for " & cfgName & " configuration\n"); fprintf(stderr, "\n"); int NV = (c.ne); ??? eDcXXX = NEW(REF Coords_t; with ( NV)^ /* Garbage gradient. */ ){ assert((v.ne) == NV); eFunction.defVar(v); eFunction.eval(c, e, TRUE, eDc); fprintf(stderr, " energy == " & FLR(e, 9, 4) & "\n"); fprintf(stderr, " vNum V Gradient (algebrical) Gradient (numerical) Difference\n"); fprintf(stderr, " ----- - ------------------------------------------- ------------------------------------------- ----------------\n"); /* Compute numerical gradient: */ for (i = 0; i < NV; i++) { fprintf(stderr, " " & Fmt.Pad(Fmt.Int(i), 5)); if (v[i]) { fprintf(stderr, " T"); fprintf(stderr, " " & FLR4(eDc[i], 10,7)); for (k = 0; k < 4; k++) { cOld = c[i][k]; c[i][k] = cOld + DiffStep; eFunction.eval(c, ep, FALSE, eDcXXX); eDcNum[k] = (ep - e)/DiffStep; c[i][k] = cOld } fprintf(stderr, " " & FLR4(eDcNum, 10,7)); fprintf(stderr, " " & ELR(r4_Dist(eDcNum, eDc[i]), 16,8)); } else { fprintf(stderr, " F"); fprintf(stderr, " " & FLR4(eDc[i], 10,7)); } fprintf(stderr, "\n") } } } /* END GradTest */ double EvalTest( pwr: Wr.T; /* File ".plot" */ eFunction: MixedEnergy.T; /* Energy function */ Coords_t *c; /* Coordinates */ Coords_t *cDs; /* Direction vector */ bool_vec_t *v; /* Which nodes are variable */ Coords_t *eDc; /* Work area for gradient */ ) double *e, ep; double eDs; /* Directional derivative */ CONST DiffStep == 0.0001; { ??? NV = (c.ne); { assert((v.ne) == NV); eFunction.defVar(v); eFunction.eval(c, e, TRUE, eDc); fprintf(pwr, " "); fprintf(pwr, " " & FLR(e, 12, 7)); /* Compute directional derivative from gradient: */ eDs = 0.0; for (i = 0; i < NV; i++){ eDs = eDs + r4_dot(eDc[i], cDs[i]); } fprintf(pwr, " " & FLR(eDs, 12, 7)); /* Check if setting "grad==FALSE" has any effect on "e": */ eFunction.eval(c, ep, FALSE, eDc); assert(ep == e); /* Compute directional derivative numerically: */ ??? ds = DiffStep; { for (i = 0; i < NV; i++){ c[i] = r4_Mix(1.0, c[i], ds, cDs[i]); } eFunction.eval(c, ep, FALSE, eDc); eDs = (ep - e)/ds } fprintf(pwr, " " & FLR(eDs, 12, 7)); } return e; } /* END EvalTest */ void WriteHeader(pwr: Wr.T) { fprintf(pwr, "#"); fprintf(pwr, " " & Fmt.Pad("s", 6)); fprintf(pwr, " "); fprintf(pwr, " " & Fmt.Pad("etot", 12)); fprintf(pwr, " " & Fmt.Pad("etotDc*cDs", 12)); fprintf(pwr, " " & Fmt.Pad("etotDs", 12)); fprintf(pwr, " "); fprintf(pwr, " " & Fmt.Pad("evar", 12)); fprintf(pwr, " " & Fmt.Pad("evarDc*cDs", 12)); fprintf(pwr, " " & Fmt.Pad("evarDs", 12)); fprintf(pwr, " "); fprintf(pwr, " " & Fmt.Pad("etot-evar", 15)); fprintf(pwr, "\n"); fprintf(pwr, "#"); fprintf(pwr, " " & Fmt.Pad("", 6, '-', Fmt.Align.Right)); fprintf(pwr, " "); fprintf(pwr, " " & Fmt.Pad("", 12, '-', Fmt.Align.Right)); fprintf(pwr, " " & Fmt.Pad("", 12, '-', Fmt.Align.Right)); fprintf(pwr, " " & Fmt.Pad("", 12, '-', Fmt.Align.Right)); fprintf(pwr, " "); fprintf(pwr, " " & Fmt.Pad("", 12, '-', Fmt.Align.Right)); fprintf(pwr, " " & Fmt.Pad("", 12, '-', Fmt.Align.Right)); fprintf(pwr, " " & Fmt.Pad("", 12, '-', Fmt.Align.Right)); fprintf(pwr, " "); fprintf(pwr, " " & Fmt.Pad("", 15, '-', Fmt.Align.Right)); fprintf(pwr, "\n"); } /* END WriteHeader */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-tpFile"); o->tpFile = argparser_get_next(pp); argparser_get_keyword(pp, "-aFile"); o->aFile = argparser_get_next(pp); argparser_get_keyword(pp, "-bFile"); o->bFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-nSteps"))) { o->nSteps = argparser_get_next_int(pp, 1, 1000); } else { o->nSteps = 100; } o->eFunction = ParseEnergyParams.Parse(pp); if (o->eFunction == NULL) { argparser_error(pp, "\"-energy\" not specified") } o->showMin = argparser_keyword_present(pp, "-showMin"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestEnergy \\\n" \ " -tpFile NAME -aFile NAME -bFile NAME \\\n" \ " -outFile \\\n" \ " [ -nSteps ] \\\n" \ " [ -showMin ] \\\n" \ ParseEnergyParams.Help \ "\n"); END¦ } } return o; } /* END GetOptions */ PROCEDURE FLR(x: double; wd, pr: uint): char *== { return Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, pr), wd); } /* END FLR */ PROCEDURE ELR(x: double; wd, pr: uint): char *== { return Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Sci, pr), wd); } /* END ELR */ PROCEDURE FLR4(x: r4_t; wd, pr: uint): char *== { return Fmt.Pad(Fmt.LongReal(x[0], Fmt.Style.Fix, pr), wd) & " " \ Fmt.Pad(Fmt.LongReal(x[1], Fmt.Style.Fix, pr), wd) & " " \ Fmt.Pad(Fmt.LongReal(x[2], Fmt.Style.Fix, pr), wd) & " " \ Fmt.Pad(Fmt.LongReal(x[3], Fmt.Style.Fix, pr), wd) } /* END FLR4 */ /* end TestEnergy */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestGeomDege.c #define PROG_NAME "TestGeomDege" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestGeomDege_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Program to find degenerations on the topologies to builds by several "Make" programs. */ #define TestGeomDege_C_author \ "Created by L. Lozada, 1999-2000.\n" \ "Modified by L.A.P.Lozada on 2000-01-19." // #INCLUDE // #INCLUDE #include #include // #INCLUDE TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ bool_t @{edge->?}; bool_t wall; bool_t all; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) e1,e2,f1,f2: REF ARRAY OF INTEGER; v : REF ARRAY OF bool_t; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { if ((o->edge) || (o->all)) { int ind = 0; /* Comment indentation. */ filefmt_write_comment(stderr, "\nTest of @{Edge->?}s\n" & "\n",ind,'|'); for (i = 0; i < top->NE; i++) { for (j = i+1; j < top->NE; j++) { ??? ei = top->edge[i].pa; ??? ej = top->edge[j].pa; Node_t ei0 = OrgV(ei)->num; ??? ei1 = OrgV(Clock(ei))->num; Node_t ej0 = OrgV(ej)->num; ??? ej1 = OrgV(Clock(ej))->num; { e1 = NEW(REF ARRAY OF INTEGER, 2); e1[0] = ei0; e1[1] = ei1; Mis.InsertionSort(1,e1); e2 = NEW(REF ARRAY OF INTEGER, 2); e2[0] = ej0; e2[1] = ej1; Mis.InsertionSort(1,e2); if ((e1[0] == e2[0]) && (e1[1] == e2[1])) { fprintf(stderr, "Failed Test Of @{Edge->?}s\n"); fprintf(stderr,Fmt.Int(e1[0]) & " "& Fmt.Int(e1[1]) & "\n"); Process.Exit¦(1); } } } } } if ((o->wall) || (o->all)) { int ind = 0; /* Comment indentation. */ filefmt_write_comment(stderr, "\nTest of Walls\n" & "\n",ind,'|'); for (i = 0; i < top->wall.ne; i++) { for (j = i+1; j < top->wall.ne; j++) { ??? fi = top->wall[i]; ??? fj = top->wall[j]; ??? pi = fi.pa; ??? pj = fj.pa; ??? ri = Octf.DegreeOfEdge(pi); ??? rj = Octf.DegreeOfEdge(pj); { if (ri == rj) { f1 = NEW(REF ARRAY OF INTEGER, ri); f2 = NEW(REF ARRAY OF INTEGER, ri); for (k = 0; k < ri; k++) { f1[k] = OrgV(pi)->num; pi = NextE(pi); f2[k] = OrgV(pj)->num; pj = NextE(pj); } Mis.InsertionSort(ri-1,f1); Mis.InsertionSort(ri-1,f2); v = NEW(REF ARRAY OF bool_t, ri); for (k = 0; k < ri; k++) { v[k] = (f1[k] == f2[k]); } INTEGER n = 0; VAR { for (k = 0; k < ri; k++) { if (v[k]){ n++; } } if (n == ri) { fprintf(stderr, "Failed Test Of Walls\n"); for (k = 0; k < ri; k++) { fprintf(stderr,Fmt.Int(f1[k]) & " "); } fprintf(stderr,"\n"); Process.Exit¦(1); } } } } } } } } } DoIt; Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); o->edge = argparser_keyword_present(pp, "-@{edge->?}"); o->wall = argparser_keyword_present(pp, "-wall"); o->all = argparser_keyword_present(pp, "-all"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestGeomDege -inFile \\\n" \ " [ -@{edge->?} | -wall | -all ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestGeomDege. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestRootElements.c #define PROG_NAME "TestRootElements" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestRootElements_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program serves as the base for the implementation of the "curvature" energies: Curv2D and Curv1D. */ #define TestRootElements_C_author \ "Created by L.A.P.lozada, 1999-2000.\n" \ "Revision:\n" \ " 06-06-2000 by lozada: Optimized the collect of the children elements." #include // #INCLUDE #include #include // #INCLUDE CONST double INIT_STACK_SIZE = 100000; /* Types */ TYPE double StackF = REF Wall_vec_t; double StackE = REF Edge_vec_t; double Element = {@{Edge->?}, Wall}; double WALLS = Wall_vec_t; double @{EDGE->?}S = Edge_vec_t; typedef struct Options_t { char *inFileTp; /* Initial guess file name (minus ".tp") */ Element element; char *elename; } double Number = RECORD INTEGER nre; /* number of "root" elements. */ uint nce; /* number of "children" elements inside each "root" element. */ } VAR str,stc: Stat.T; /* statistical accumulators to the number of "root" elements and the number of "children" elements inside each "root" element. */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Number *num; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToTaMa(o->inFileTp); ??? top = tc.top; { if (o->element == Element.Wall) { num = WallStatistics(top); fprintf(stderr, Fmt.Int(num.nre) & " " & Fmt.Int(num.nce) & "\n"); ??? cf = CropChilWalls(top; with (num) ){ fprintf(stderr,"Children walls of the root wall \n"); for (i = 0; i < num.nre; i++) { fprintf(stderr, Fmt.Pad(Fmt.Int(i),3) & ": "); for (j = 0; j < num.nce; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(cf[i,j]->num), 5) & " "); } fprintf(stderr,"\n"); } } } else { num = @{Edge->?}Statistics(top); fprintf(stderr, Fmt.Int(num.nre) & " " & Fmt.Int(num.nce) & "\n"); ??? ce = CropChil@{Edge->?}s(top; with (num) ){ fprintf(stderr,"Children @{edge->?}s of the root @{edge->?} \n"); for (i = 0; i < num.nre; i++) { fprintf(stderr, Fmt.Pad(Fmt.Int(i),3) & ": "); for (j = 0; j < num.nce; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(ce[i,j]->num), 5) & " "); } fprintf(stderr,"\n"); } } } return 0; } PROCEDURE CropChilWalls( ElemTableRec_t *top; Number *num; ) : REF ARRAY OF StackF == topi : REF uint_vec_t; /* Crop the "children" walls for each "root" wall. */ { /* initialize the "top" indexes for each of the "num.nre" stacks of walls. */ topi = NEW(REF uint_vec_t , num.nre); for (k = 0; k < num.nre; k++){ topi[k] = 0; } ??? t = NEW(REF ARRAY OF StackF, num.nre); with ( ){ for (k = 0; k < num.nre; k++) { t[k] = Wall_vec_new(INIT_STACK_SIZE); } for (j = 0; j < top->wall.ne; j++) { ??? f = top->wall[j]; with ( double fr = f->root DO if (fr!=-1){ SaveF(t[fr],topi[fr],f); } } } return t; } } /* END CropChilWalls */ PROCEDURE CropChil@{Edge->?}s( ElemTableRec_t *top; Number *num; ): REF ARRAY OF StackE == /* Crop the "children" @{edge->?}s for each "root" @{edge->?}. */ topj : REF uint_vec_t; { /* initialize the "top" indexes for each of the "num.nre" stacks of @{edge->?}s. */ topj = NEW(REF uint_vec_t , num.nre); for (k = 0; k < num.nre; k++){ topj[k] = 0; } ??? t = NEW(REF ARRAY OF StackE; with ( num.nre) ){ for (k = 0; k < num.nre; k++) { t[k] = Edge_vec_new(INIT_STACK_SIZE); } for (j = 0; j < top->NE; j++) { ??? e = top->edge[j]; with ( double er = e->root DO if (er!=-1){ SaveE(t[er],topj[er],e); } } } return t; } } /* END CropChil@{Edge->?}s */ Number WallStatistics(ElemTableRec_t *top) /* Compute the number of "root" walls and the number of "children" walls. */ Number *num; { for (i = 0; i < top->wall.ne; i++){ ??? f = top->wall[i]; ??? fr = FLOAT(f->root, REAL), ); with( ) { Stat.Accum(str,fr); if (fr == 0.0){ Stat.Accum(stc,fr); } } } num.nre = FLOOR(str.maximum)+1; num.nce = FLOOR(stc->num); return num; } /* END WallStatistics */ PROCEDURE @{Edge->?}Statistics(ElemTableRec_t *top) : Number == /* Compute the number of "root" @{edge->?}s and the number of "children" @{edge->?}s. */ Number *num; { for (i = 0; i < top->NE; i++){ ??? e = top->edge[i]; ??? er = FLOAT(e->root, REAL)); with( ) { Stat.Accum(str,er); if (er == 0.0){ Stat.Accum(stc,er); } } } num.nre = FLOOR(str.maximum)+1; num.nce = FLOOR(stc->num); return num; } /* END @{Edge->?}Statistics */ PROCEDURE SaveF( StackF *Stack; uint *top; Wall *wall; ) /* Save the wall "wall" on the stack "Stack" */ { Stack.El[top] = wall; top = top +1 } /* END SaveF */ PROCEDURE SaveE( StackE *Stack; uint *top; @{Edge->?} *@{edge->?}; ) /* Save the edge "@{edge->?}" on the stack "Stack" */ { Stack.El[top] = @{edge->?}; top = top +1 } /* END SaveE */ /* UNUSED */ PROCEDURE CollectChil@{Edge->?}s( ElemTableRec_t *top; Number *num; ): REF ARRAY OF @{EDGE->?}S == uint *NT; { ??? t = NEW(REF ARRAY OF @{EDGE->?}S; with ( num.nre, num.nce) ){ for (i = 0; i < num.nre; i++) { NT = 0; for (j = 0; j < top->NE; j++) { ??? e = top->edge[j]; ??? er = e->root; { if (er == i){ t[i,NT] = e; NT++; } } } } return t; } } /* END CollectChil@{Edge->?}s */ /* UNUSED */ PROCEDURE CollectChilWalls( ElemTableRec_t *top; Number *num; ) : REF ARRAY OF WALLS == uint *NT; { ??? t = NEW(REF ARRAY OF WALLS; with ( num.nre, num.nce) ){ for (i = 0; i < num.nre; i++) { NT = 0; for (j = 0; j < top->wall.ne; j++) { ??? f = top->wall[j]; ??? fr = f->root; { if (fr == i){ t[i,NT] = f; NT++; } } } } return t; } } /* END CollectChilWalls */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-element"); o->elename = argparser_get_next(pp); if (0 == strcmp(o->elename, "@{edge->?}"))) { o->element = Element.edge } else if (0 == strcmp(o->elename, "wall"))){ o->element = Element.Wall } else { argparser_error(pp, "bad element \"" & argparser_get_next(pp) & "\"\n") } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestRootElements " \ " -inFileTp \\\n" \ " -element { @{edge->?} | wall }\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestRootElements. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestSubdivideEdge.c /* See {TestSubdivide@{Edge->?}.h} */ // #INCLUDE ?}.h> /* This program subdivides an @{edge->?} and propagates the subdivision for the star of this @{edge->?}. Teste with success in the subdivision of bipyramids and in the Refine- Triang program. */ #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // // #INCLUDE // Place_t, Org, MakeElemTable, Makewedge, MakeNode, SetOrg, SetOrgAll, Pneg, SetPnegOfNearbyWalls, @{Node->?}, Node; // #INCLUDE // NextF, Clock, NextE, PrevE, SetNextE, SetRingEdgeInfo, SetRingWallInfo, SetNextF; // #INCLUDE // MakeTriangle; uint NVE = 0; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; ??? e = top->edge[0]; ??? a = e.pa; ??? dfr = Octf.DegreeOfWall(a); { Subdivide@{Edge->?}(a,dfr,top); ??? newtop = MakeElemTable(a); ??? nc = GenCoords(newtop)^; ??? cmt = " "; { WriteTopology(o->outFile, newtop, cmt); WriteState(o->outFile, newtop, nc, cmt); WriteMaterials(o->outFile, newtop, cmt); } return 0; } PROCEDURE Subdivide@{Edge->?}( Place_t @pn; uint n; ElemTableRec_t *top; ) == VAR @{Node->?} x; a,bn,m1,m2,m3,t0,t1,Place_vec_t t2; wn,p: REF ARRAY OF @{Node->?}; { a = NEW(REF Place_vec_t,n); bn = NEW(REF Place_vec_t,n); m1 = NEW(REF Place_vec_t,n); m2 = NEW(REF Place_vec_t,n); m3 = NEW(REF Place_vec_t,n); t0 = NEW(REF Place_vec_t,n); t1 = NEW(REF Place_vec_t,n); t2 = NEW(REF Place_vec_t,n); /* save the @places */ a = NEW(REF Place_vec_t,n); a[0] = an; ??? f = PWedge(a[0]).wall; ??? e = PEdge(a[0]); ??? ee = PEdge(NextE(a[0])); ??? ee_ = PEdge(PrevE(a[0])); { if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; if (top->edge[e->num]->exists ){ e->exists = TRUE; } else { e->exists = FALSE; } e.color = top->edge[e->num].color; e.transp = top->edge[e->num].transp; e.radius = top->edge[e->num].radius; if (top->edge[ee->num]->exists ){ ee->exists = TRUE; } else { ee->exists = FALSE; } ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; if (top->edge[ee_->num]->exists ){ ee_->exists = TRUE; } else { ee_->exists = FALSE; } ee_.color = top->edge[ee_->num].color; ee_.transp = top->edge[ee_->num].transp; ee_.radius = top->edge[ee_->num].radius; } for (i = 1; i < n; i++) { a[i] = NextF(a[i-1]); ??? f = PWedge(a[i]).wall; ??? ee = PEdge(NextE(a[i])); ??? ee_ = PEdge(PrevE(a[i])); { if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; if (top->edge[ee->num]->exists ){ ee->exists = TRUE; } else { ee->exists = FALSE; } ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; if (top->edge[ee_->num]->exists ){ ee_->exists = TRUE; } else { ee_->exists = FALSE; } ee_.color = top->edge[ee_->num].color; ee_.transp = top->edge[ee_->num].transp; ee_.radius = top->edge[ee_->num].radius; } } /* save the nodes */ wn = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { wn[i] = Org(PrevE(a[i])); } /* save the tetrahedra */ p = NEW(REF ARRAY OF @{Node->?},n); for (i = 0; i < n; i++) { p[i] = Pneg(a[i]); } /* save other @places */ bn = NEW(REF Place_vec_t,n); for (i = 0; i < n; i++) { bn[i] = Clock(PrevE(NextF(PrevE(a[i])))); ??? e = PEdge(bn[i]); ??? f = PWedge(bn[i]).wall; { if (top->edge[e->num]->exists ){ e->exists = TRUE; } else { e->exists = FALSE; } e.color = top->edge[e->num].color; e.transp = top->edge[e->num].transp; e.radius = top->edge[e->num].radius; if (top->wall[f->num]->exists ){ f->exists = TRUE; } else { f->exists = FALSE; } f.color = top->wall[f->num].color; f.transp = top->wall[f->num].transp; } } /* insert wedges and edges */ for (i = 0; i < n; i++) { m1[i] = MakeWedge(); m2[i] = MakeWedge(); m3[i] = MakeWedge(); t0[i] = MakeTriangle(); t1[i] = NextE(t0[i]); t2[i] = NextE(t1[i]); ??? f = PWedge(t0[i]).wall; ??? e0 = PEdge(t0[i]); ??? e1 = PEdge(t1[i]); ??? e2 = PEdge(t2[i]); { f->exists = FALSE; f.transp = (frgb_t){1.0,1.0,1.0}; e1->exists = FALSE; e2->exists = FALSE; e1.radius = 0.003; e1.transp = (frgb_t){1.0,1.0,1.0}; e2.radius = 0.003; e2.transp = (frgb_t){1.0,1.0,1.0}; if ((PEdge(bn[i])->exists )){ e0->exists = TRUE; } else { e0->exists = FALSE; } } } /* Now, subdivide @{edge->?} and extend the subdivision on the edge's stars */ x = MakeNode(); ??? v = (Node_t)(x); { ){ v.label = "VE"; if ((PEdge(a[0])->exists)) { v.radius = PEdge(a[0]).radius; v.color = PEdge(a[0]).color; v.transp = PEdge(a[0]).transp; } else { v.radius = 0.00; v.color = (frgb_t){1.0,1.0,1.0}; v.transp = (frgb_t){1.0,1.0,1.0}; } v->num = NVE; NVE++; } for (j = 0; j < n; j++) { Place_t b = NextE(a[j]); Edge_t be = PEdge(b); Place_t c = NextE(b); Edge_t ce = PEdge(c); ??? u = Org(a[j]); ??? v = Org(b); ??? w = Org(c); with ( /* save the attributes of the edge-wall component of the @place a[j] */ double f = PWedge(a[j]).wall; double fe = f->exists; double fc = f.color; double ft = f.transp; double g = PWedge(m3[j]).wall; double ge = g->exists; double gc = g.color; double gt = g.transp; double h = PEdge(m3[j]) ){ SetNextE(a[j],m1[j]); SetNextE(m1[j],c); SetNextE(m2[j],m3[j]); SetNextE(m3[j],Clock(b)); SetOrg(a[j], u); SetOrg(Clock(a[j]), x); SetOrg(m2[j],v); SetOrg(Clock(m2[j]), x); SetOrg(m3[j], x); SetOrg(Clock(m3[j]), w); SetOrg(m1[j], x); SetOrg(Clock(m1[j]), w); SetNextF(m1[j],m3[j]); /* set the attributes for the wall component */ SetRingWallInfo(a[j],f); SetRingWallInfo(m3[j],g); if (fe) { ge = TRUE; } else { ge = FALSE; } gc = fc; gt = ft; SetRingEdgeInfo(m3[j],h); SetRingEdgeInfo(b,be); SetRingEdgeInfo(c,ce); SetRingWallInfo(bn[j],PWedge(bn[j]).wall); SetRingWallInfo(NextF(bn[j]),PWedge(NextF(bn[j])).wall); } } for (j = 0; j < n; j++) { SetNextF(Clock(m2[j]),Clock(m2[(j+1) % n])); } ??? k = PEdge(m2[0]); ??? e = PEdge(a[0]); ??? ee = e->exists; ??? er = e.radius; ??? ec = e.color; ??? et = e.transp; ??? ke = k->exists; ??? kr = k.radius; ??? kc = k.color; ??? kt = k.transp; { if (ee){ ke = TRUE; }else{ ke = FALSE; } kr = er; kc = ec; kt = et; SetRingEdgeInfo(a[0],e); SetRingEdgeInfo(m2[0],k); } for (j = 0; j < n; j++) { Place_t cn = NextF(bn[j]); ??? e1 = PEdge(t1[j]); ??? e2 = PEdge(t2[j]); Wall_t cnf = PWall(cn); Edge_t cne = PEdge(cn); { if (top->wall[cnf->num]->exists ){ cnf->exists = TRUE; } else { cnf->exists = FALSE; } cnf.color = top->wall[cnf->num].color; cnf.transp = top->wall[cnf->num].transp; if (top->edge[cne->num]->exists ){ cne->exists = TRUE; } else { cne->exists = FALSE; } cne.color = top->edge[cne->num].color; cne.transp = top->edge[cne->num].transp; cne.radius = top->edge[cne->num].radius; /* set the origins */ SetOrgAll(t0[j],wn[j]); SetOrgAll(t1[j],wn[(j+1) % n]); SetOrgAll(t2[j],x); SetNextF(bn[j], t0[j]); SetNextF(t0[j],cn); SetNextF(m1[j],t2[j]); SetNextF(t2[j],m3[j]); SetNextF(Clock(m1[(j+1) % n]), t1[j]); SetNextF(t1[j],Clock(m3[(j+1) % n])); SetRingEdgeInfo(t0[j],PEdge(cn)); SetRingEdgeInfo(t1[j],e1); SetRingEdgeInfo(t2[j],e2); } } /* insert cells */ for (j = 0; j < n; j++) { ??? q = Triangulation.MakeCell(); { SetPnegOfNearbyWalls(a[j],p[j]); SetPnegOfNearbyWalls(m2[j],q); } } } /* END Subdivide@{Edge->?} */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestSubdivide@{Edge->?}" \ " -inFile -outFile \n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestSubdivide@{Edge->?}. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestSubdivideTetra.c #define PROG_NAME "TestSubdivideTetra" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestSubdivideTetra_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Testing The SubdivideTetrahedron procedure. */ #include // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // // #INCLUDE // Place_t, Org, MakeElemTable, @{Node->?},Node,MakeCell, MakeNode, SetOrgAll, SetPnegOfNearbyWalls, Topology, Coords_t, OrgV, Pneg, Ppos; // #INCLUDE // NextF, Clock, NextE, PrevE, PrevF, Spin, SetRingEdgeInfo, SetRingWallInfo, SetNextF, Tors; // #INCLUDE // MakeTriangle; uint NVP = 0; X : REF r4_vec_t; ElemTableRec_t oldtop; /* Was {oldtopology} */; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFile); ??? c = rc^; ??? nc = NEW(REF Coords_t; with (top->node.ne+top->cell.ne)^, double cmt = "Created by Selective Subdivision of : " & o->outFile ){ /* Subdivision of degenerative tetrahedra */ fprintf(stderr, "Eliminating degenerative tetrahedra\n"); for (j = 0; j < top->cell.ne; j++) { ??? r = Srot(top->cell[j]); Place_t a = Tors(r); { SubdivideTetrahedron(a,top,c,nc); } } ??? newtop = MakeElemTable(top->wedge[1]); { WriteTopology(o->outFile, newtop, cmt & ".tp\n" & "on " & Today()); WriteState(o->outFile,newtop, nc, cmt & ".st\n" & "on " & Today()); WriteMaterials(o->outFile, newtop, cmt & ".ma\n" & "on " & Today()); } return 0; } PROCEDURE SubdivideTetrahedron(Place_t @p, ElemTableRec_t *top; *co: Coords_t; VAR nc: Coords_t) /* Subdivide a degenerative tetrahedron in four new tetrahedra through the insertion of a new medial node of type "VP" more six walls and three @{edge->?}s. */ @{Node->?} *y; { /* Create the medial node "VP" */ y = MakeNode(); ??? vv = (Node_t)(y); { double b = PrevF(a); double c = PrevE(b); double d = NextF(c); double e = PrevE(a); double f = PrevF(e); double g = PrevE(f); double h = NextF(g); double fa = PWall(a); double fb = PWall(b); double fg = PWall(g); double fh = PWall(h); double ea = PEdge(a); double ec = PEdge(c); double ee = PEdge(e); double eh = PEdge(h); eeb = PEdge(NextE(b)), eea = PEdge(NextE(a)), double i = NextE(a); double j = PrevF(i); double k = NextE(b); double l = NextF(k); double u = OrgV(a); double v = OrgV(Clock(a)); double w = OrgV(c); double x = OrgV(e); double f1 = MakeTriangle(); double f2 = MakeTriangle(); double f3 = MakeTriangle(); double f4 = MakeTriangle(); double f5 = MakeTriangle(); double f6 = MakeTriangle(); double q1 = MakeCell(); double q2 = MakeCell(); double q3 = MakeCell(); double q4 = MakeCell() ){ vv.label = "VP"; vv.radius = 0.0001; vv.transp = (frgb_t){1.0,1.0,1.0}; vv.color = (frgb_t){1.0,1.0,1.0}; vv->num = NVP; NVP++; nc[u->num] = co.e[u->num]; nc[v->num] = co.e[v->num]; nc[w->num] = co.e[w->num]; nc[x->num] = co.e[x->num]; nc[vv->num] = r4_Scale(0.25, r4_Add(co.e[u->num], r4_Add(r4_Add(co.e[v->num],co.e[w->num]),co.e[x->num]))); /* save attributes for the original walls: "fa", "fb", "fg", "fh". */ fa->exists = top->wall[fa->num]->exists; fa.color = top->wall[fa->num].color; fa.transp = top->wall[fa->num].transp; fb->exists = top->wall[fb->num]->exists; fb.color = top->wall[fb->num].color; fb.transp = top->wall[fb->num].transp; fg->exists = top->wall[fg->num]->exists; fg.color = top->wall[fg->num].color; fg.transp = top->wall[fg->num].transp; fh->exists = top->wall[fh->num]->exists; fh.color = top->wall[fh->num].color; fh.transp = top->wall[fh->num].transp; /* save attributes for the original edgess: "ea", "ec", "ee", "eh", "eeb", and "eea". */ ea->exists = top->edge[ea->num]->exists; ea.color = top->edge[ea->num].color; ea.transp = top->edge[ea->num].transp; ea.radius = top->edge[ea->num].radius; ec->exists = top->edge[ec->num]->exists; ec.color = top->edge[ec->num].color; ec.transp = top->edge[ec->num].transp; ec.radius = top->edge[ec->num].radius; ee->exists = top->edge[ee->num]->exists; ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; eh->exists = top->edge[eh->num]->exists; eh.color = top->edge[eh->num].color; eh.transp = top->edge[eh->num].transp; eh.radius = top->edge[eh->num].radius; eea->exists = top->edge[eea->num]->exists; eea.color = top->edge[eea->num].color; eea.transp = top->edge[eea->num].transp; eea.radius = top->edge[eea->num].radius; eeb->exists = top->edge[eeb->num]->exists; eeb.color = top->edge[eeb->num].color; eeb.transp = top->edge[eeb->num].transp; eeb.radius = top->edge[eeb->num].radius; /* set the attributes for the new internal walls */ PWall(f1)->exists = FALSE; PWall(f2)->exists = FALSE; PWall(f3)->exists = FALSE; PWall(f4)->exists = FALSE; PWall(f5)->exists = FALSE; PWall(f6)->exists = FALSE; PWall(f1).color = (frgb_t){1.0,1.0,1.0}; PWall(f2).color = (frgb_t){1.0,1.0,1.0}; PWall(f3).color = (frgb_t){1.0,1.0,1.0}; PWall(f4).color = (frgb_t){1.0,1.0,1.0}; PWall(f5).color = (frgb_t){1.0,1.0,1.0}; PWall(f6).color = (frgb_t){1.0,1.0,1.0}; PWall(f1).transp = (frgb_t){1.0,1.0,1.0}; PWall(f2).transp = (frgb_t){1.0,1.0,1.0}; PWall(f3).transp = (frgb_t){1.0,1.0,1.0}; PWall(f4).transp = (frgb_t){1.0,1.0,1.0}; PWall(f5).transp = (frgb_t){1.0,1.0,1.0}; PWall(f6).transp = (frgb_t){1.0,1.0,1.0}; /* insert f1 */ SetNextF(b,f1); SetNextF(f1,a); /* insert f2 */ SetNextF(c,f2); SetNextF(f2,d); /* insert f3 */ SetNextF(f,f3); SetNextF(f3,e); /* set the relations among f1,f2 and f3 */ SetNextF(Clock(NextE(f2)),PrevE(f1)); SetNextF(PrevE(f1),Clock(NextE(f3))); SetNextF(Clock(NextE(f3)),Clock(NextE(f2))); SetRingEdgeInfo(PrevE(f1), PEdge(PrevE(f1))); PEdge(PrevE(f1))->exists = FALSE; PEdge(PrevE(f1)).color = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f1)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f1)).radius = 0.004; /* insert f4 */ SetNextF(j,f4); SetNextF(f4,i); /* insert f5 */ SetNextF(k,f5); SetNextF(f5,l); /* insert f6 */ SetNextF(g,f6); SetNextF(f6,h); /* set the internal relations along @{edge->?} "yv" */ SetNextF(PrevE(f5),PrevE(f4)); SetNextF(PrevE(f4),Clock(NextE(f1))); SetNextF(Clock(NextE(f1)), PrevE(f5)); SetRingEdgeInfo(Clock(NextE(f1)),PEdge(Clock(NextE(f1)))); PEdge(NextE(f1))->exists = FALSE; PEdge(NextE(f1)).color = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f1)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f1)).radius = 0.004; /* set the internal relations along @{edge->?} "wy" */ SetNextF(NextE(f5),Clock(PrevE(f6))); SetNextF(Clock(PrevE(f6)),Clock(PrevE(f2))); SetNextF(Clock(PrevE(f2)),NextE(f5)); SetRingEdgeInfo(NextE(f5),PEdge(NextE(f5))); PEdge(NextE(f5))->exists = FALSE; PEdge(NextE(f5)).color = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f5)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f5)).radius = 0.004; /* set the internal relations along @{edge->?} "xy" */ SetNextF(NextE(f6), NextE(f4)); SetNextF(NextE(f4), Clock(PrevE(f3))); SetNextF(Clock(PrevE(f3)), NextE(f6)); SetRingEdgeInfo(NextE(f4), PEdge(NextE(f4))); PEdge(NextE(f4))->exists = FALSE; PEdge(NextE(f4)).color = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f4)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f4)).radius = 0.004; /* set the overall @{edge->?} component */ SetRingEdgeInfo(a, ea); SetRingEdgeInfo(c, ec); SetRingEdgeInfo(e, ee); SetRingEdgeInfo(i, eea); SetRingEdgeInfo(k, eeb); SetRingEdgeInfo(h, eh); SetRingWallInfo(a, fa); SetRingWallInfo(b, fb); SetRingWallInfo(g, fg); SetRingWallInfo(h, fh); /* set the origins */ SetOrgAll(a,u); SetOrgAll(Clock(a),v); SetOrgAll(c,w); SetOrgAll(e,x); SetOrgAll(PrevE(f1),y); /* set the cells */ SetPnegOfNearbyWalls(a,q1); SetPnegOfNearbyWalls(Spin(b),q2); SetPnegOfNearbyWalls(Spin(g),q3); SetPnegOfNearbyWalls(Spin(f6),q4); } } /* END SubdivideTetrahedron */ /* PROCEDURE FixaTetrahedron(Place_t @p, Coords_t *c, VAR nc: Coords_t) /* */ { assert(! (Pneg(a)!=NULL) && (Ppos(a)!=NULL)); Node_t u = OrgV(a); Node_t v = OrgV(Clock(a)); Node_t x = OrgV(PrevE(a)); Node_t w = OrgV(PrevE(NextF(a))); Node_t y = OrgV(PrevE(PrevF(a))); { Mis.WriteInt(stderr, u->num); Mis.WriteInt(stderr, v->num); Mis.WriteInt(stderr, w->num); Mis.WriteInt(stderr, x->num); Mis.WriteInt(stderr, y->num); fprintf(stderr, y.label); } } FixaTetrahedron; */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestSubdivideTetra \\\n" \ " -inFile -outFile \\\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestSubdivideTetra. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestSubdivideTetrahedron.c #define PROG_NAME "TestSubdivideTetrahedron" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestSubdivideTetrahedron_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Testing The SubdivideTetrahedron procedure. */ // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // // #INCLUDE // Place_t, Org, MakeElemTable, @{Node->?},Node,MakeCell, // #INCLUDE // NextF, Clock, NextE, PrevE, PrevF, Spin, SetRingEdgeInfo, SetRingWallInfo, SetNextF, Tors; // #INCLUDE // MakeTriangle; uint NVP = 0; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { /* Subdivision of degenerative tetrahedra */ fprintf(stderr, "Eliminating degenerative tetrahedra\n"); for (j = 0; j < top->cell.ne; j++) { ??? r = Srot(top->cell[j]); Place_t a = Tors(r); { SubdivideTetrahedron(a,top); } } ??? newtop = MakeElemTable(top->wedge[1]; with (1), double nc = GenCoords(newtop)^; double cmt = "Created by Selective Subdivision of : " & o->outFile ){ WriteTopology(o->outFile, newtop, cmt & ".tp\n" & "on " & Today()); WriteState(o->outFile,newtop, nc, cmt & ".st\n" & "on " & Today()); Triangulation.FindDegeneracies(newtop); WriteMaterials(o->outFile, newtop, cmt & ".ma\n" & "on " & Today()); } return 0; } PROCEDURE SubdivideTetrahedron(Place_t @p, ElemTableRec_t *top) /* Subdivide a degenerative tetrahedron in four new tetrahedra through the insertion of a new medial node of type "VP" more six walls and three @{edge->?}s. */ @{Node->?} *y; { /* Create the medial node "VP" */ y = MakeNode(); ??? v = (Node_t)(y); { ){ v.label = "VP"; v.radius = 0.00; v.transp = (frgb_t){1.0,1.0,1.0}; v.color = (frgb_t){1.0,1.0,1.0}; v->num = NVP; NVP++; } Place_t b = PrevF(a); Place_t c = PrevE(b); Place_t d = NextF(c); Place_t e = PrevE(a); Place_t f = PrevF(e); Place_t g = PrevE(f); Place_t h = NextF(g); Wall_t fa = PWall(a); Wall_t fb = PWall(b); Wall_t fg = PWall(g); Wall_t fh = PWall(h); Edge_t ea = PEdge(a); Edge_t ec = PEdge(c); Edge_t ee = PEdge(e); Edge_t eh = PEdge(h); Edge_t eeb = PEdge(NextE(b)); Edge_t eea = PEdge(NextE(a)); Place_t i = NextE(a); Place_t j = PrevF(i); Place_t k = NextE(b); Place_t l = NextF(k); ??? u = Org(a); ??? v = Org(Clock(a)); ??? w = Org(c); ??? x = Org(e); ??? f1 = MakeTriangle(); ??? f2 = MakeTriangle(); ??? f3 = MakeTriangle(); ??? f4 = MakeTriangle(); ??? f5 = MakeTriangle(); ??? f6 = MakeTriangle(); Cell_t q1 = MakeCell(); Cell_t q2 = MakeCell(); Cell_t q3 = MakeCell(); Cell_t q4 = MakeCell(); { /* save attributes for the original walls: "fa", "fb", "fg", "fh". */ fa->exists = top->wall[fa->num]->exists; fa.color = top->wall[fa->num].color; fa.transp = top->wall[fa->num].transp; fb->exists = top->wall[fb->num]->exists; fb.color = top->wall[fb->num].color; fb.transp = top->wall[fb->num].transp; fg->exists = top->wall[fg->num]->exists; fg.color = top->wall[fg->num].color; fg.transp = top->wall[fg->num].transp; fh->exists = top->wall[fh->num]->exists; fh.color = top->wall[fh->num].color; fh.transp = top->wall[fh->num].transp; /* save attributes for the original edgess: "ea", "ec", "ee", "eh", "eeb", and "eea". */ ea->exists = top->edge[ea->num]->exists; ea.color = top->edge[ea->num].color; ea.transp = top->edge[ea->num].transp; ea.radius = top->edge[ea->num].radius; ec->exists = top->edge[ec->num]->exists; ec.color = top->edge[ec->num].color; ec.transp = top->edge[ec->num].transp; ec.radius = top->edge[ec->num].radius; ee->exists = top->edge[ee->num]->exists; ee.color = top->edge[ee->num].color; ee.transp = top->edge[ee->num].transp; ee.radius = top->edge[ee->num].radius; eh->exists = top->edge[eh->num]->exists; eh.color = top->edge[eh->num].color; eh.transp = top->edge[eh->num].transp; eh.radius = top->edge[eh->num].radius; eea->exists = top->edge[eea->num]->exists; eea.color = top->edge[eea->num].color; eea.transp = top->edge[eea->num].transp; eea.radius = top->edge[eea->num].radius; eeb->exists = top->edge[eeb->num]->exists; eeb.color = top->edge[eeb->num].color; eeb.transp = top->edge[eeb->num].transp; eeb.radius = top->edge[eeb->num].radius; /* set the attributes for the new internal walls */ PWall(f1)->exists = FALSE; PWall(f2)->exists = FALSE; PWall(f3)->exists = FALSE; PWall(f4)->exists = FALSE; PWall(f5)->exists = FALSE; PWall(f6)->exists = FALSE; PWall(f1).color = (frgb_t){1.0,1.0,1.0}; PWall(f2).color = (frgb_t){1.0,1.0,1.0}; PWall(f3).color = (frgb_t){1.0,1.0,1.0}; PWall(f4).color = (frgb_t){1.0,1.0,1.0}; PWall(f5).color = (frgb_t){1.0,1.0,1.0}; PWall(f6).color = (frgb_t){1.0,1.0,1.0}; PWall(f1).transp = (frgb_t){1.0,1.0,1.0}; PWall(f2).transp = (frgb_t){1.0,1.0,1.0}; PWall(f3).transp = (frgb_t){1.0,1.0,1.0}; PWall(f4).transp = (frgb_t){1.0,1.0,1.0}; PWall(f5).transp = (frgb_t){1.0,1.0,1.0}; PWall(f6).transp = (frgb_t){1.0,1.0,1.0}; /* insert f1 */ SetNextF(b,f1); SetNextF(f1,a); /* insert f2 */ SetNextF(c,f2); SetNextF(f2,d); /* insert f3 */ SetNextF(f,f3); SetNextF(f3,e); /* set the relations among f1,f2 and f3 */ SetNextF(Clock(NextE(f2)),PrevE(f1)); SetNextF(PrevE(f1),Clock(NextE(f3))); SetNextF(Clock(NextE(f3)),Clock(NextE(f2))); SetRingEdgeInfo(PrevE(f1), PEdge(PrevE(f1))); PEdge(PrevE(f1))->exists = FALSE; PEdge(PrevE(f1)).color = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f1)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f1)).radius = 0.004; /* insert f4 */ SetNextF(j,f4); SetNextF(f4,i); /* insert f5 */ SetNextF(k,f5); SetNextF(f5,l); /* insert f6 */ SetNextF(g,f6); SetNextF(f6,h); /* set the internal relations along @{edge->?} "yv" */ SetNextF(PrevE(f5),PrevE(f4)); SetNextF(PrevE(f4),Clock(NextE(f1))); SetNextF(Clock(NextE(f1)), PrevE(f5)); SetRingEdgeInfo(Clock(NextE(f1)),PEdge(Clock(NextE(f1)))); PEdge(NextE(f1))->exists = FALSE; PEdge(NextE(f1)).color = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f1)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f1)).radius = 0.004; /* set the internal relations along @{edge->?} "wy" */ SetNextF(NextE(f5),Clock(PrevE(f6))); SetNextF(Clock(PrevE(f6)),Clock(PrevE(f2))); SetNextF(Clock(PrevE(f2)),NextE(f5)); SetRingEdgeInfo(NextE(f5),PEdge(NextE(f5))); PEdge(NextE(f5))->exists = FALSE; PEdge(NextE(f5)).color = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f5)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f5)).radius = 0.004; /* set the internal relations along @{edge->?} "xy" */ SetNextF(NextE(f6), NextE(f4)); SetNextF(NextE(f4), Clock(PrevE(f3))); SetNextF(Clock(PrevE(f3)), NextE(f6)); SetRingEdgeInfo(NextE(f4), PEdge(NextE(f4))); PEdge(NextE(f4))->exists = FALSE; PEdge(NextE(f4)).color = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f4)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(NextE(f4)).radius = 0.004; /* set the overall @{edge->?} component */ SetRingEdgeInfo(a, ea); SetRingEdgeInfo(c, ec); SetRingEdgeInfo(e, ee); SetRingEdgeInfo(i, eea); SetRingEdgeInfo(k, eeb); SetRingEdgeInfo(h, eh); SetRingWallInfo(a, fa); SetRingWallInfo(b, fb); SetRingWallInfo(g, fg); SetRingWallInfo(h, fh); /* set the origins */ SetOrgAll(a,u); SetOrgAll(Clock(a),v); SetOrgAll(c,w); SetOrgAll(e,x); SetOrgAll(PrevE(f1),y); /* set the cells */ SetPnegOfNearbyWalls(a,q1); SetPnegOfNearbyWalls(Spin(b),q2); SetPnegOfNearbyWalls(Spin(g),q3); SetPnegOfNearbyWalls(Spin(f6),q4); } } /* END SubdivideTetrahedron */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestSubdivideTetrahedron\\\n" \ " -inFile -outFile \\\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestSubdivideTetrahedron. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestSubdivideWall.c #define PROG_NAME "TestSubdivideWall" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestSubdivideWall_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Testing the SubdivideWall procedure. */ // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include // #INCLUDE // // #INCLUDE // Place_t, Org, MakeElemTable, @{Node->?}, Node, MakeCell, Makewedge, MakeNode, SetOrgAll, SetPnegOfNearbyWalls, PnegP, PposP; // #INCLUDE // NextF, Clock, NextE, PrevE, PrevF, SetNextE, SetRingEdgeInfo, SetRingWallInfo, SetNextF; // #INCLUDE // MakeTriangle; VAR NVF = 0; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { /* Subdivision of degenerative walls */ fprintf(stderr, "Eliminating degenerative walls\n"); for (j = 0; j < top->wall.ne; j++) { ??? f = top->wall[j]; ??? a = f.pa; { IF((PnegP(a)!=NULL)) && ((PposP(a) #NULL)))) { SubdivideWall(a,top); } } } ??? newtop = MakeElemTable(top->wedge[0]); ??? nc = GenCoords(newtop)^; ??? cmt = "Created by Selective Subdivision of : " & o->outFile; { WriteTopology(o->outFile, newtop, cmt & ".tp\n" & "on " & Today()); WriteState(o->outFile,newtop, nc, cmt & ".st\n" & "on " & Today()); WriteMaterials(o->outFile, newtop, cmt & ".ma\n" & "on " & Today()); } return 0; } PROCEDURE SubdivideWall(Place_t @p, ElemTableRec_t *top) /* Subdivide a degenerative triangular wall in three new walls through the insertion of a new medial node of type "VF" and six wall-@{edge->?} @places. Then, expand this subdivision on the wall's star. */ VAR @{Node->?} x; { /* Create the medial node "VF" */ x = MakeNode(); ??? v = (Node_t)(x); { ){ v.label = "VF"; v.radius = 0.000; v.transp = (frgb_t){1.0,1.0,1.0}; v.color = (frgb_t){1.0,1.0,1.0}; v->num = NVF; NVF++; } Wall_t fa = PWall(a); Edge_t ea = PEdge(a); Place_t b = NextE(a); Edge_t eb = PEdge(b); Place_t c = PrevE(a); Edge_t ec = PEdge(c); Place_t af = NextF(a); Place_t bf = NextF(b); Place_t cf = NextF(c); Place_t af_ = PrevF(a); Place_t bf_ = PrevF(b); Place_t cf_ = PrevF(c); Edge_t eaf = PEdge(PrevE(af)); Edge_t eaf_ = PEdge(PrevE(af_)); Wall_t faf = PWall(af); Wall_t faf_ = PWall(af_); Edge_t ebf = PEdge(PrevE(bf)); Edge_t ebf_ = PEdge(PrevE(bf_)); Wall_t fbf = PWall(bf); Wall_t fbf_ = PWall(bf_); Edge_t ecf = PEdge(PrevE(cf)); Edge_t ecf_ = PEdge(PrevE(cf_)); Wall_t fcf = PWall(cf); ??? fcf_ == PWall(cf_), ??? u = Org(a); ??? v = Org(b); ??? w = Org(c); Place_t d = MakeWedge(); Place_t e = MakeWedge(); Place_t f = MakeWedge(); Place_t g = MakeWedge(); Place_t h = MakeWedge(); Place_t i = MakeWedge(); Wall_t df = PWall(d); Wall_t ff = PWall(f); Wall_t hf = PWall(h); /* new walls to insert on the wall's star */ ??? f1 = MakeTriangle(); ??? f2 = MakeTriangle(); ??? f3 = MakeTriangle(); ??? f4 = MakeTriangle(); ??? f5 = MakeTriangle(); ??? f6 = MakeTriangle(); Cell_t q1 = MakeCell(); Cell_t q2 = MakeCell(); Cell_t q3 = MakeCell(); Cell_t q4 = MakeCell(); Cell_t q5 = MakeCell(); Cell_t q6 = MakeCell(); { if (top->wall[fa->num]->exists) { df->exists = TRUE; ff->exists = TRUE; hf->exists = TRUE; } else { df->exists = FALSE; ff->exists = FALSE; hf->exists = FALSE; } df.color = top->wall[fa->num].color; df.transp = top->wall[fa->num].transp; ff.color = top->wall[fa->num].color; ff.transp = top->wall[fa->num].transp; hf.color = top->wall[fa->num].color; hf.transp = top->wall[fa->num].transp; /* first link connecting the @place "a" */ SetNextE(a,d); SetNextE(d,e); SetNextE(e,a); SetRingWallInfo(d,df); /* second link connecting the @place "b" */ SetNextE(b,f); SetNextE(f,g); SetNextE(g,b); SetRingWallInfo(f,ff); /* third link connecting the @place "c" */ SetNextE(c,h); SetNextE(h,i); SetNextE(i,c); SetRingWallInfo(h,hf); /* save information about the original edges "PEdge(a)": "ea" */ ea->exists = top->edge[ea->num]->exists; ea.color = top->edge[ea->num].color; ea.transp = top->edge[ea->num].transp; ea.radius = top->edge[ea->num].radius; /* save information about the original edges "PEdge(b)": "eb" */ eb->exists = top->edge[eb->num]->exists; eb.color = top->edge[eb->num].color; eb.transp = top->edge[eb->num].transp; eb.radius = top->edge[eb->num].radius; /* save information about the original edges "PEdge(c)": "ec" */ ec->exists = top->edge[ec->num]->exists; ec.color = top->edge[ec->num].color; ec.transp = top->edge[ec->num].transp; ec.radius = top->edge[ec->num].radius; /* save information about the wall "PWall(af)" : "faf" */ faf->exists = top->wall[faf->num]->exists; faf.color = top->wall[faf->num].color; faf.transp = top->wall[faf->num].transp; /* save information about the edge "PEdge(af)" : "eaf" */ eaf->exists = top->edge[eaf->num]->exists; eaf.color = top->edge[eaf->num].color; eaf.transp = top->edge[eaf->num].transp; eaf.radius = top->edge[eaf->num].radius; /* save information about the wall "PWall(af_)" : "faf_" */ faf_->exists = top->wall[faf_->num]->exists; faf_.color = top->wall[faf_->num].color; faf_.transp= top->wall[faf_->num].transp; /* save information about the edge "PEdge(af_)" : "eaf_" */ eaf_->exists = top->edge[eaf_->num]->exists; eaf_.color = top->edge[eaf_->num].color; eaf_.transp = top->edge[eaf_->num].transp; eaf_.radius = top->edge[eaf_->num].radius; /* save information about the wall "PWall(bf)" : "fbf" */ fbf->exists = top->wall[fbf->num]->exists; fbf.color = top->wall[fbf->num].color; fbf.transp= top->wall[fbf->num].transp; /* save information about the edge "PEdge(bf)" : "ebf" */ ebf->exists = top->edge[ebf->num]->exists; ebf.color = top->edge[ebf->num].color; ebf.transp = top->edge[ebf->num].transp; ebf.radius = top->edge[ebf->num].radius; /* save information about the wall "PWall(bf_)" : "fbf_" */ fbf_->exists= top->wall[fbf_->num]->exists; fbf_.color = top->wall[fbf_->num].color; fbf_.transp= top->wall[fbf_->num].transp; /* save information about the edge "PEdge(bf_)" : "ebf_" */ ebf_->exists = top->edge[ebf_->num]->exists; ebf_.color = top->edge[ebf_->num].color; ebf_.transp = top->edge[ebf_->num].transp; ebf_.radius = top->edge[ebf_->num].radius; /* save information about the wall "PWall(cf)" : "fcf" */ fcf->exists = top->wall[fcf->num]->exists; fcf.color = top->wall[fcf->num].color; fcf.transp= top->wall[fcf->num].transp; /* save information about the edge "PEdge(cf)" : "ecf" */ ecf->exists = top->edge[ecf->num]->exists; ecf.color = top->edge[ecf->num].color; ecf.transp = top->edge[ecf->num].transp; ecf.radius = top->edge[ecf->num].radius; /* save information about the wall "PWall(cf_)" : "fcf_" */ fcf_->exists = top->wall[fcf_->num]->exists; fcf_.color = top->wall[fcf_->num].color; fcf_.transp= top->wall[fcf_->num].transp; /* save information about the edge "PEdge(cf_)" : "ecf_" */ ecf_->exists = top->edge[ecf_->num]->exists; ecf_.color = top->edge[ecf_->num].color; ecf_.transp = top->edge[ecf_->num].transp; ecf_.radius = top->edge[ecf_->num].radius; /* set the attributes for the internal walls */ PWall(f1)->exists = FALSE; PWall(f2)->exists = FALSE; PWall(f3)->exists = FALSE; PWall(f4)->exists = FALSE; PWall(f5)->exists = FALSE; PWall(f6)->exists = FALSE; PWall(f1).color = (frgb_t){1.0,1.0,1.0}; PWall(f2).color = (frgb_t){1.0,1.0,1.0}; PWall(f3).color = (frgb_t){1.0,1.0,1.0}; PWall(f4).color = (frgb_t){1.0,1.0,1.0}; PWall(f5).color = (frgb_t){1.0,1.0,1.0}; PWall(f6).color = (frgb_t){1.0,1.0,1.0}; PWall(f1).transp = (frgb_t){1.0,1.0,1.0}; PWall(f2).transp = (frgb_t){1.0,1.0,1.0}; PWall(f3).transp = (frgb_t){1.0,1.0,1.0}; PWall(f4).transp = (frgb_t){1.0,1.0,1.0}; PWall(f5).transp = (frgb_t){1.0,1.0,1.0}; PWall(f6).transp = (frgb_t){1.0,1.0,1.0}; /* Now make the connections in the interior of wall */ SetNextF(g,Clock(d)); SetNextF(i,Clock(f)); SetNextF(e,Clock(h)); /* Now subdivide the "Ppos(a)" tetrahedron ( the superior tetrahedron in my plan */ /* first we, insert f1 */ SetNextF(d, Clock(f1)); SetNextF(Clock(f1), Clock(g)); assert(NextF(Clock(g)) == d); SetNextF(NextE(f1),NextE(af)); SetNextF(Clock(PrevE(bf)), NextE(f1)); /* now, we insert f2 */ SetNextF(f, Clock(f2)); SetNextF(Clock(f2), Clock(i)); assert(NextF(Clock(i)) == f); SetNextF(NextE(f2),NextE(bf)); SetNextF(Clock(PrevE(cf)), NextE(f2)); /* now, we insert f3 */ SetNextF(h, Clock(f3)); SetNextF(Clock(f3), Clock(e)); assert(NextF(Clock(e)) == h); SetNextF(NextE(f3),NextE(cf)); SetNextF(Clock(PrevE(af)), NextE(f3)); /* now make connections between the internal walls inserted */ SetNextF(PrevE(f1),PrevE(f3)); SetNextF(PrevE(f3),PrevE(f2)); assert(NextF(PrevE(f2)) == PrevE(f1)); /* set the superior axial @{edge->?} */ SetRingEdgeInfo(PrevE(f1), PEdge(PrevE(f1))); /* OK */ PEdge(PrevE(f1))->exists = FALSE; PEdge(PrevE(f1)).color = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f1)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f1)).radius = 0.004; /* Now subdivide the "Pneg(a)" tetrahedron ( the inferior tetrahedron in my plan */ /* now, we insert f4 */ SetNextF(Clock(g), Clock(f4)); assert(NextF(Clock(f4)) == d); SetNextF(NextE(af_), NextE(f4)); SetNextF(NextE(f4), Clock(PrevE(bf_))); /* now, we insert f5 */ SetNextF(Clock(i), Clock(f5)); assert(NextF(Clock(f5)) == f); SetNextF(NextE(bf_), NextE(f5)); SetNextF(NextE(f5), Clock(PrevE(cf_))); /* now, we insert f6 */ SetNextF(Clock(e), Clock(f6)); assert(NextF(Clock(f6)) == h); SetNextF(NextE(cf_), NextE(f6)); SetNextF(NextE(f6), Clock(PrevE(af_))); /* now make connections between the internal walls inserted */ SetNextF(PrevE(f4),PrevE(f5)); SetNextF(PrevE(f5),PrevE(f6)); assert(NextF(PrevE(f6)) == PrevE(f4)); /* set the inferior axial @{edge->?} */ SetRingEdgeInfo(PrevE(f4), PEdge(PrevE(f4))); /* OK */ PEdge(PrevE(f4))->exists = FALSE; PEdge(PrevE(f4)).color = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f4)).transp = (frgb_t){1.0,1.0,1.0}; PEdge(PrevE(f4)).radius = 0.004; /* set the origins */ SetOrgAll(f1, x); SetOrgAll(a, u); SetOrgAll(b, v); SetOrgAll(c, w); SetOrgAll(PrevE(f1), OrgV(PrevE(af))); SetOrgAll(PrevE(f4), OrgV(PrevE(af_))); /* set the new internal @{edge->?}s */ SetRingEdgeInfo(f1,PEdge(f1)); PEdge(f1)->exists = FALSE; PEdge(f1).color = (frgb_t){1.0,1.0,1.0}; PEdge(f1).transp = (frgb_t){1.0,1.0,1.0}; PEdge(f1).radius = 0.004; SetRingEdgeInfo(f2,PEdge(f2)); PEdge(f2)->exists = FALSE; PEdge(f2).color = (frgb_t){1.0,1.0,1.0}; PEdge(f2).transp = (frgb_t){1.0,1.0,1.0}; PEdge(f2).radius = 0.004; SetRingEdgeInfo(f3,PEdge(f3)); PEdge(f3)->exists = FALSE; PEdge(f3).color = (frgb_t){1.0,1.0,1.0}; PEdge(f3).transp = (frgb_t){1.0,1.0,1.0}; PEdge(f3).radius = 0.004; /* set the original edgess and walls in the superior level */ SetRingEdgeInfo(PrevE(af),eaf); SetRingEdgeInfo(PrevE(bf),ebf); SetRingEdgeInfo(PrevE(cf),ecf); SetRingWallInfo(af,faf); SetRingWallInfo(bf,fbf); SetRingWallInfo(cf,fcf); /* set the original edgess and walls in the inferior label */ SetRingEdgeInfo(PrevE(af_),eaf_); SetRingEdgeInfo(PrevE(bf_),ebf_); SetRingEdgeInfo(PrevE(cf_),ecf_); SetRingWallInfo(af_,faf_); SetRingWallInfo(bf_,fbf_); SetRingWallInfo(cf_,fcf_); /* set the original edgess in the half label */ SetRingEdgeInfo(a,ea); SetRingEdgeInfo(b,eb); SetRingEdgeInfo(c,ec); SetPnegOfNearbyWalls(Clock(PrevE(f1)),q1); SetPnegOfNearbyWalls(Clock(PrevE(f2)),q2); SetPnegOfNearbyWalls(Clock(PrevE(f3)),q3); SetPnegOfNearbyWalls(PrevE(f4),q4); SetPnegOfNearbyWalls(PrevE(f5),q5); SetPnegOfNearbyWalls(PrevE(f6),q6); } } /* END SubdivideWall */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TestSubdivideWall \\\n" \ " -inFile -outFile \\\n"); END¦ } } return o; } /* END GetOptions */ /* UNUSED */ uint NumInternalWalls(ElemTableRec_t *top) number: uint = 0; { for (j = 0; j < top->wall.ne; j++){ ??? a = top->wall[j].pa; { if (((PposP(a)!=NULL)) && ((PnegP(a)!=NULL))){ number++; } } } return number; } NumInternalWalls; { DoIt() } TestSubdivideWall. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TesteElasticity.c #define PROG_NAME "TesteElasticity" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TesteElasticity_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " #include #include // #INCLUDE #include #include #include CONST double A = LR3x3.T { (r3_t){0.0, 1.0, 1.0}, (r3_t){1.0, 0.0, 1.0}, (r3_t){1.0, 1.0, 0.0} } double B = LR4x4.T { (r4_t){0.0, 0.0, 0.0, 1.0}, (r4_t){0.0, 1.0, 1.0, 1.0}, (r4_t){1.0, 1.0, 0.0, 1.0}, (r4_t){1.0, 0.0, 1.0, 1.0} } TYPE double LR4x3 = ARRAY [0..3] OF r3_t; double LR3x4 = ARRAY [0..2] OF r4_t; LR4x3 Transpose_3x4(*m: LR3x4) /* Return the transpose of a matrix 3x4. */ t : LR4x3; { t[0] = (r3_t){m[0,0], m[1,0], m[2,0]}; t[1] = (r3_t){m[0,1], m[1,1], m[2,1]}; t[2] = (r3_t){m[0,2], m[1,2], m[2,2]}; t[3] = (r3_t){m[0,3], m[1,3], m[2,3]}; return t; } /* END Transpose_3x4 */ LR3x4 Transpose_4x3(*m: LR4x3) /* return the transpose of a matrix 3x3. */ t : LR3x4; { t[0] = (r4_t){m[0,0], m[1,0], m[2,0], m[3,0]}; t[1] = (r4_t){m[0,1], m[1,1], m[2,1], m[3,1]}; t[2] = (r4_t){m[0,2], m[1,2], m[2,2], m[3,2]}; return t; } /* END Transpose_4x3 */ LR4x3 Mul_4x3_3x3(*a: LR4x3; *b: LR3x3.T) /* Return the product of the matrix "a" 4x3 and matrix "b" 3x3. */ c : LR4x3; { ??? a00 = a[0; with (0], a01 == a[0,1], a02 == a[0,2], double a10 = a[1,0], a11 == a[1,1], a12 == a[1,2]; double a20 = a[2,0], a21 == a[2,1], a22 == a[2,2]; double a30 = a[3,0], a31 == a[3,1], a32 == a[3,2]; double b00 = b[0,0], b01 == b[0,1], b02 == b[0,2]; double b10 = b[1,0], b11 == b[1,1], b12 == b[1,2]; double b20 = b[2,0], b21 == b[2,1], b22 == b[2,2]; double c00 = a00 * b00 + a01 * b10 + a02 * b20; double c01 = a00 * b01 + a01 * b11 + a02 * b21; double c02 = a00 * b02 + a01 * b12 + a02 * b22; double c10 = a10 * b00 + a11 * b10 + a12 * b20; double c11 = a10 * b01 + a11 * b11 + a12 * b21; double c12 = a10 * b02 + a11 * b12 + a12 * b22; double c20 = a20 * b00 + a21 * b10 + a22 * b20; double c21 = a20 * b01 + a21 * b11 + a22 * b21; double c22 = a20 * b02 + a21 * b12 + a22 * b22; double c30 = a30 * b00 + a31 * b10 + a32 * b20; double c31 = a30 * b01 + a31 * b11 + a32 * b21; double c32 = a30 * b02 + a31 * b12 + a32 * b22; double c0 = (r3_t){c00,c01,c02}; double c1 = (r3_t){c10,c11,c12}; double c2 = (r3_t){c20,c21,c22}; double c3 = (r3_t){c30,c31,c32} ){ c[0] = c0; c[1] = c1; c[2] = c2; c[3] = c3; return c; } } /* END Mul_4x3_3x3 */ LR3x3.T Mul_3x4_4x3(*a: LR3x4; *b: LR4x3) /* Return the product of the matrix "a" 3x4 and matrix "b" 4x3. */ { ??? a00 = a[0; with (0], a01 == a[0,1], a02 == a[0,2], a03 == a[0,3], double a10 = a[1,0], a11 == a[1,1], a12 == a[1,2], a13 == a[1,3]; double a20 = a[2,0], a21 == a[2,1], a22 == a[2,2], a23 == a[2,3]; double b00 = b[0,0], b01 == b[0,1], b02 == b[0,2]; double b10 = b[1,0], b11 == b[1,1], b12 == b[1,2]; double b20 = b[2,0], b21 == b[2,1], b22 == b[2,2]; double b30 = b[3,0], b31 == b[3,1], b32 == b[3,2]; double c00 = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30; double c01 = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31; double c02 = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32; double c10 = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30; double c11 = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31; double c12 = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32; double c20 = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30; double c21 = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31; double c22 = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32; double c0 = (r3_t){c00,c01,c02}; double c1 = (r3_t){c10,c11,c12}; double c2 = (r3_t){c20,c21,c22} ){ return LR3x3.T{c0,c1,c2}; } } /* END Mul_3x4_4x3 */ PROCEDURE PrintMatrix_3x3(*a: LR3x3.T) { for (i = 0; i < 3; i++){ for (j = 0; j < 3; j++) { Mis.WriteLong(stderr, a[i,j]); fprintf(stderr, " "); } fprintf(stderr, "\n"); } } /* END PrintMatrix_3x3 */ PROCEDURE PrintMatrix_3x4(*a: LR3x4) { for (i = 0; i < 3; i++){ for (j = 0; j < 4; j++) { Mis.WriteLong(stderr, a[i,j]); fprintf(stderr, " "); } fprintf(stderr, "\n"); } } /* END PrintMatrix_3x4 */ PROCEDURE PrintMatrix_4x3(*a: LR4x3) { for (i = 0; i < 4; i++){ for (j = 0; j < 3; j++) { Mis.WriteLong(stderr, a[i,j]); fprintf(stderr, " "); } fprintf(stderr, "\n"); } } /* END PrintMatrix_4x3 */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) B : LR4x3; { with ( double b0 = (r3_t){10.0, 10.0, 10.0}; double b1 = (r3_t){10.0, 10.0, 10.0}; double b2 = (r3_t){10.0, 10.0, 10.0}; double b3 = (r3_t){10.0, 10.0, 10.0} ){ B[0] = b0; B[1] = b1; B[2] = b2; B[3] = b3; fprintf(stderr, "\nMatrix A\n"); PrintMatrix_3x3(A); fprintf(stderr, "\nMatrix B\n"); PrintMatrix_4x3(B); fprintf(stderr, "\nMatrix A_1\n"); PrintMatrix_3x3(LR3x3.Inv(A)); fprintf(stderr, "\nMatrix A* A_1\n"); PrintMatrix_3x3(LR3x3.Mul(A,LR3x3.Inv(A))); /* fprintf(stderr, "\nMatrix B'\n"); PrintMatrix_3x4(Transpose_4x3(B)); fprintf(stderr, "\nMatrix B''\n"); PrintMatrix_4x3(Transpose_3x4(Transpose_4x3(B))); fprintf(stderr, "\nMatrix BxA\n"); PrintMatrix_4x3(Mul_4x3_3x3(B,A)); fprintf(stderr, "\nMatrix B'xB\n"); PrintMatrix_3x3(Mul_3x4_4x3(Transpose_4x3(B),B)); */ fprintf(stderr, "\nMatrix BxA_1\n"); PrintMatrix_4x3(Mul_4x3_3x3(B,LR3x3.Inv(A))); return 0; } { DoIt(); fprintf(stderr, "volume :" & Fmt.LongReal(1.0/6.0*LR3x3.Det(A)) \ "\n"); } TesteElasticity. /* Copyright © 1999 Universidade Estadual de Campinas (UNICAMP) */ /* Testes Matrix A 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 Matrix B 1.00 0.00 0.00 0.00 2.00 0.00 0.00 0.00 3.00 1.00 1.00 1.00 Matrix B' 1.00 0.00 0.00 1.00 0.00 2.00 0.00 1.00 0.00 0.00 3.00 1.00 Matrix B'' 1.00 0.00 0.00 0.00 2.00 0.00 0.00 0.00 3.00 1.00 1.00 1.00 Matrix BxA 1.00 0.00 0.00 0.00 2.00 0.00 0.00 0.00 3.00 1.00 1.00 1.00 Matrix B'xB 2.00 1.00 1.00 1.00 5.00 1.00 1.00 1.00 10.00 */~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cur/progs-more/TesteOpGeo.c /* Programa para testar os procedientos Geometricos no R4 */ #define TesteOpGeo_C_author \ "Created by L. P. Lozada, 1999-2000." // #INCLUDE // #INCLUDE #include #include #include // #INCLUDE TYPE double RowT = ARRAY [1..4] OF double; double Wedge_t = TriangulationWedge_t; double Place_t = TriangulationPlace_t; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ } /* UNUSED */ PROCEDURE PrtNextF(Place_t @p) { fprintf(stdout, "a: "); Octf.PrintPlace(stdout, a, 1); fprintf(stdout, " NextF(a): "); Octf.PrintPlace(stdout, NextF(a), 1); fprintf(stdout, "\n"); } /* END PrtNextF */ /* UNUSED */ PROCEDURE Poly(Place_t @p) @{Node->?} *p; { Octf.PrintPlace(stdout, a, 5); fprintf(stdout, " "); p = Pneg(a); fprintf(Stdio.stdout, "Pneg->num: " & Fmt.Pad(Fmt.Int(p->num),2) & "\n"); } /* END Poly */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) bool_t *iso; b,nb,vn,n : r4_t; mvd, mel, n1, n2 : double; uint d; v : REF r4_vec_t; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.Read(o->inFile); ??? top = tc.top; ??? cmt = tc.cmt; ??? c = tc.c^; { /* for (j = 0; j < 6; j++) { ??? a = top->wall[j].pa^; ??? p1 = PnegP(a)->num; ??? p2 = PposP(a)->num; ??? t = Srot(top->cell[p1]); Place_t a = Tors(t); Place_t t1 = Clock(PrevE(t)); Place_t a1 = Tors(t1); Node_t un = OrgV(a)->num; Node_t vn = OrgV(NextE(a))->num; Node_t wn = OrgV(PrevE(a))->num; Node_t xn = OrgV(PrevE(a1))->num; ??? tt = Srot(top->cell[p2]); Place_t aa = Tors(tt); Place_t tt1 = Clock(PrevE(tt)); Place_t aa1 = Tors(tt1); ??? u1n = OrgV(aa)->num; ??? v1n = OrgV(NextE(aa))->num; ??? w1n = OrgV(PrevE(aa))->num; ??? x1n = OrgV(PrevE(aa1))->num; { fprintf(stdout, Fmt.Pad(Fmt.Int(un), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(vn), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(wn), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(xn), 5) & "\n"); fprintf(stdout, Fmt.Pad(Fmt.Int(u1n), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(v1n), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(w1n), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(x1n), 5) & "\n"); fprintf(stdout, "\n"); } } fprintf(stdout, "\n"); for (i = 0; i < top->node.ne; i++) { ??? poly1 = Triangulation.StarOfNode(top->node[i],top); { for(i = 0; i < poly1.ne; i++) { fprintf(Stdio.stdout, Fmt.Int(poly1[i][0]->num) & " "); fprintf(Stdio.stdout, Fmt.Int(poly1[i][1]->num) & " "); fprintf(Stdio.stdout, Fmt.Int(poly1[i][2]->num) & " "); fprintf(Stdio.stdout, Fmt.Int(poly1[i][3]->num) & "\n"); } } fprintf(stdout, "\n"); } for (i = 0; i < top->node.ne; i++) { ??? a = top->node[i]; { fprintf(Stdio.stdout, " Org->num: " & Fmt.Int(Org(a)->num) & " "); d = Triangulation.DegreeOfNode(a); fprintf(stdout, " Degree : " & Fmt.Int(d) & "\n"); d = Triangulation->numberPolyOfStar(a,top); fprintf(stdout, " Number of Poly on the star: " & Fmt.Int(d) \ "\n"); Mis.WriteComments(stdout, "\nThe Vetor Normal is: "); vn = Triangulation.NodeNormal(a, c, top); Mis.WritePoint(vn); n2 = r4_Norm(vn); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); nb = Triangulation.NeighborBarycenter(a,c); Mis.WriteComments(stdout, "\nThe Neighbor Barycenter is: "); Mis.WritePoint(nb); fprintf(stdout, "\n"); } } fprintf(stdout, "\n"); Mis.WriteComments(stdout, "\nThe All Node Normal are: "); v = Triangulation.ComputeAllNodeNormals(top,c); for (i = 0; i < top->node.ne; i++) { Mis.WritePoint(v[i]); n2 = r4_Norm(v[i]); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); } fprintf(stdout, "\n"); Mis.WriteComments(stdout, "\nThe All @{Edge->?} Normal are: "); v = Triangulation.ComputeAllEdgeNormals(top,c); for (i = 0; i < top->NE; i++) { Mis.WritePoint(v[i]); n2 = r4_Norm(v[i]); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); } fprintf(stdout, "\n"); Mis.WriteComments(stdout, "\nThe All Wall Normal are: "); v = Triangulation.ComputeAllWallNormals(top,c); for (i = 0; i < top->wall.ne; i++) { Mis.WritePoint(v[i]); n2 = r4_Norm(v[i]); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); } Mis.WriteComments(stdout, "\nThe All Cell Normal are: "); v = Triangulation.ComputeAllCellNormals(top,c); for (i = 0; i < top->cell.ne; i++) { Mis.WritePoint(v[i]); n2 = r4_Norm(v[i]); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); } for (i = 0; i <= (0); i++) { Octf.EnumWedges(top->wedge[0], PrtNextF, FALSE); } Mis.WriteComments(stdout, "\nTests of of geometric tools procedures " \ "and the procedure Read\n" & "\n"); b = Triangulation.Barycenter(top,c); Mis.WriteComments(stdout, "\n" & "The Barycenter is: \n"); fprintf(stdout, "ola\n"); */ Mis.WriteComments(stdout, "\nThe node coordenates\n" & "\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint(Stdio.stdout, c[v->num]); fprintf(Stdio.stdout, "\n"); } } b = Triangulation.Barycenter(top,c); Mis.WriteComments(stdout, "\n" & "The Barycenter is: \n"); mvd = Triangulation.MeanNodeDistance(top,c); Mis.WriteComments(stdout, "\nThe Average distance of nodes is: " \ Fmt.LongReal(mvd, Fmt.Style.Fix, prec = 4) & "\n"); /* mel = Triangulation.MeanEdgeLength(top,c); Mis.WriteComments(stdout, "\nThe Average length of @{edge->?}s is: " \ Fmt.LongReal(mel, Fmt.Style.Fix, prec = 4) & "\n"); Triangulation.Displace(top,RowT{5.0,5.0,5.0,5.0},c); Mis.WriteComments(stdout, "\nThe node coordenates displace" \ " 5.0,5.0,5.0,5.0\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint(Stdio.stdout, c[v->num]); fprintf(Stdio.stdout, "\n"); } } mvd = Triangulation.MeanNodeDistance(top,c); Mis.WriteComments(stdout, "\nThe Average distance of nodes is: " \ Fmt.LongReal(mvd, Fmt.Style.Fix, prec = 4) & "\n"); */ Triangulation.NormalizeNodeDistance(top,c); /* Mis.WriteComments(stdout, "\nThe Normalize Node Distance\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint(Stdio.stdout,c[v->num]); fprintf(Stdio.stdout, "\n"); } } mvd = Triangulation.MeanNodeDistance(top,c); Mis.WriteComments(stdout, "\nThe Average distance of nodes is: " \ Fmt.LongReal(mvd, Fmt.Style.Fix, prec = 4) & "\n"); Triangulation.Scale(top,10.0,c); Mis.WriteComments(stdout, "\nThe node coordenates scale 10.0\n" \ "\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint(Stdio.stdout,c[v->num]); fprintf(Stdio.stdout, "\n"); } } Triangulation.NormalizeNodeDistance(top,c); Mis.WriteComments(stdout, "\nThe Normalize Node Distance\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint(Stdio.stdout,c[v->num]); fprintf(Stdio.stdout, "\n"); } } */ mvd = Triangulation.MeanNodeDistance(top,c); Mis.WriteComments(stdout, "\nThe Average distance of nodes is: " \ Fmt.LongReal(mvd, Fmt.Style.Fix, prec = 4) & "\n"); b = Triangulation.Barycenter(top,c); Mis.WriteComments(stdout, "\n" & "The Barycenter is: \n"); /* Triangulation.NormalizeNodeDistance(top,c); mvd = Triangulation.MeanNodeDistance(top,c); Mis.WriteComments(stdout, "\nThe Average distance of nodes normalized is: " \ Fmt.LongReal(mvd, Fmt.Style.Fix, prec = 4) & "\n"); Triangulation.NormalizeEdgeLengths(top,c); mel = Triangulation.MeanEdgeLength(top,c); Mis.WriteComments(stdout, "\nThe Average length of @{edge->?}s normalized is: " & Fmt.LongReal(mel, Fmt.Style.Fix, prec = 4) & "\n"); for (i = 0; i < top->NE; i++) { ??? a = top->edge[i].pa^; { PEdge(a)->exists = TRUE; d = Octf.DegreeRingWalls(a); fprintf(Stdio.stdout, " Degree Ring Wall is: "); fprintf(Stdio.stdout, Fmt.Int(d) & "\n"); n = Triangulation.EdgeNormal(a,c); Mis.WriteComments(stdout, "\nthe edge Normal is: "); Mis.WritePoint(n); n1 = r4_Norm(n); fprintf(Stdio.stdout, ", Their Norma is: "); fprintf(Stdio.stdout, Fmt.LongReal(n1, Fmt.Style.Fix, prec = 3) & "\n"); } } Mis.WriteComments(stdout, "\nThe Vetor Cross is: "); vn = Triangulation.NodeCross(a, c); Mis.WritePoint(vn); n1 = r4_Norm(vn); fprintf(Stdio.stdout, ", Their Norma is: "); fprintf(Stdio.stdout, Fmt.LongReal(n1, Fmt.Style.Fix, prec = 3) & "\n"); Mis.WriteComments(stdout, "\nThe Vetor Normal is: "); vn = Triangulation.NodeNormal(a, c); Mis.WritePoint(vn); n2 = r4_Norm(vn); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); Mis.WriteComments(stdout, "\nThe All Node Normal are: "); v = Triangulation.ComputeAllNodeNormals(top,c); for (i = 0; i < top->node.ne; i++) { ??? a = top->node[i]; { d = Triangulation.DegreeOfNode(a); Mis.WriteComments(stdout, "\n" \ "The Degree of Origin the @place Spin(ac1) is: " & Fmt.Int(d) & "\n"); } }; for (i = 0; i < top->node.ne; i++) { Mis.WritePoint(v[i]); n2 = r4_Norm(vn); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); }; } } Mis.WriteComments(stdout, "\nThe All Wall Normal are: "); for (i = 0; i < top->wall.ne; i++) { ??? a = top->wall[i].pa^; { vn = Triangulation.WallNormal(a,c); Mis.WritePoint(vn); n2 = r4_Norm(vn); fprintf(Stdio.stdout, ", Their norm is : "); fprintf(Stdio.stdout, Fmt.LongReal(n2, Fmt.Style.Fix, prec = 3) & "\n"); } }; } iso = Triangulation.TriviallyIsomorphic(top, top); if (! iso) { Mis.WriteComments(stdout, "Complexes are not isomorphic\n"); } else { Mis.WriteComments(stdout, "Complexes are isomorphic\n"); } Mis.WriteComments(stdout, "\nThe out register\n" & "\n"); for (i = 0; i < top->node.ne; i++) { ??? v = top->node[i]; { fprintf(stdout, " top->node[" & Fmt.Int(i) & "]:"); Octf.PrintPlace(stdout, v,4); fprintf(Stdio.stdout, "\n"); }; } Mis.WriteComments(stdout, "\nThe region register\n" & "\n"); for (i = 0; i < top->cell.ne; i++) { ??? p = Srot(top.cell[i]); { fprintf(stdout," Srot(top->cell[" & Fmt.Pad(Fmt.Int(i),2) & "]):"); Octf.PrintPlace(stdout, p,4); fprintf(Stdio.stdout, "\n"); }; } Mis.WriteComments(stdout, "\nTests of Procedure Read\n"); Mis.WriteComments(stdout, cmt); fprintf(stdout, "Read.NV: " & Fmt.Int(top->node.ne) & "\n"); fprintf(stdout, "Read.NE: " & Fmt.Int(top->NE) & "\n"); fprintf(stdout, "Read.NF: " & Fmt.Int(top->wall.ne) & "\n"); fprintf(stdout, "Read.NP: " & Fmt.Int(top->cell.ne) & "\n"); fprintf(stdout, "Read.NFE: " & Fmt.Int(top->wall.nelE) & "\n"); fprintf(stdout, o->inFile & "\n"); Mis.WriteComments(stdout, "\nNode data by Read\n" & "\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { /* fprintf(stdout, Fmt.Pad(Fmt.Int(v->num),2) & " "); if (v->exists) { fprintf(stdout, "T" & " "); } else { fprintf(stdout, "F" & " "); } if (v.fixed) { fprintf(stdout, "T" & " "); } else { fprintf(stdout, "F" & " "); } Mis.WritePoint(c[v->num]); Mis.WriteColor(v.color); fprintf(stdout, " " & Fmt.Real(v.radius) & "\n"); fprintf(stdout, "\n"); }; } Mis.WriteComments(stdout, "\n@{Edge->?} data by Read\n" & "\n"); for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { fprintf(stdout, Fmt.Pad(Fmt.Int(e->num),2) & " "); Octf.PrintPlace(stdout, e.pa^, 4); if (e->exists) { fprintf(stdout, " T" & " "); } else { fprintf(stdout, " F" & " "); } if (e.spring) { fprintf(stdout, " T" & " "); } else { fprintf(stdout, " F" & " "); } Mis.WriteColor(e.color); fprintf(stdout, " " & Fmt.Real(e.radius) & "\n"); }; } Mis.WriteComments(stdout, "\nWall data by Read\n" & "\n"); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { fprintf(stdout, Fmt.Pad(Fmt.Int(f->num),2) & " "); if (f->exists) { fprintf(stdout, " T" & " "); } else { fprintf(stdout, " F" & " "); } Mis.WriteColor(f.color); fprintf(stdout, " "); Mis.WriteColor(f.transp); fprintf(stdout, "\n"); }; } Mis.WriteComments(stdout, "\nCell data by Read\n" & "\n"); for (i = 0; i < top->cell.ne; i++) { ??? p = top->cell[i]; { fprintf(stdout, Fmt.Pad(Fmt.Int(p->num),2) & " "); if (p->exists) { fprintf(stdout, " T" & " "); } else { fprintf(stdout, " F" & " "); } Mis.WriteColor(p.color); fprintf(stdout, " "); Mis.WriteColor(p.transp); fprintf(stdout, "\n"); }; } Mis.WriteComments(stdout, "\nwedge data by Read\n" & "\n"); for (i = 0; i < top->wall.nelE; i++) { ??? fe = NARROW(PWedge(top->wedge[i]), Wedge_t); { fprintf(stdout, Fmt.Pad(Fmt.Int(fe->num),4) & " "); Octf.PrintWedge(stdout,fe,5); fprintf(stdout, " "); VAR sPlace_t @p = top->wedge[i]; { for (j = 0; j < 4; j++) { ??? n = Org(sa); { TYPECASE n OF break; case NULL: assert(FALSE); | Node(v) ==> fprintf(stdout, Fmt.Pad(Fmt.Int(v->num), 2) & "v "); | Cell(p) ==> fprintf(stdout, Fmt.Pad(Fmt.Int(p->num), 2) & "p "); } else { assert(FALSE); } } sa = Srot(sa); } } if (fe->exists) { fprintf(stdout, " T" & " "); } else { fprintf(stdout, " F" & " "); } fprintf(stdout, "\n"); } } Mis.WriteComments(stdout, "\nAnother informations\n" & "\n"); for (i = 0; i < top->wall.nelE; i++) { VAR sPlace_t @p = top->wedge[i]; { for (j = 0; j < 4; j++) { ??? n = Org(sa); { TYPECASE n OF break; case NULL: assert(FALSE); | Node(v) ==> fprintf(stdout, " top->node[" \ Fmt.Int(v->num) & "]:"); Octf.PrintPlace(stdout, top->node[v->num], 4); | Cell(p) ==> fprintf(stdout," Srot(top->cell[" \ Fmt.Pad(Fmt.Int(p->num),2) & "]):"); Octf.PrintPlace(stdout, Srot(top->cell[p->num]), 4); } else { assert(FALSE); } } sa = Srot(sa); } fprintf(stdout, "\n"); }; } for (i = 0; i < top->cell.ne; i++) { fprintf(Stdio.stdout, "Cell: " & Fmt.Pad(Fmt.Int(i),2) & "===>"); ??? v = Srot(top.cell[i]), a == Tors(v); { Place_t ae = NextE(a); Place_t aee = NextE(ae); Place_t aff = PrevF(a); Node_t k = OrgV(a)->num; Node_t l = OrgV(ae)->num; Node_t m = OrgV(aee)->num; Node_t n = OrgV(PrevE(aff))->num; { assert(Pneg(a)->num == i); assert(Pneg(Clock(aff)) == Pneg(a)); fprintf(stdout, Fmt.Pad(Fmt.Int(k), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(l), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(m), 5) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(n), 5) & "\n"); } }; } for (i = 0; i < top->cell.ne; i++) { ??? p = top->cell[i]; ??? p1 = p.node[0]->num; ??? p2 = p.node[1]->num; ??? p3 = p.node[2]->num; ??? p4 = p.node[3]->num; { fprintf(stdout, Fmt.Pad(Fmt.Int(p1), 2) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(p2), 2) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(p3), 2) & " "); fprintf(stdout, Fmt.Pad(Fmt.Int(p4), 2) & "\n"); }; } Mis.WriteComments(stdout, "\nNode data by Read\n" & "\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint(c[v->num]); fprintf(stdout, "\n"); }; } } */ } /* END DoIt */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Read" \ " -inFile " \ "\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TesteOpGeo. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TestePolyTopology.c #define PROG_NAME "TestePolyTopology" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TestePolyTopology_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " // #INCLUDE #include #include // #INCLUDE // #INCLUDE // MakeCellTopology, Pneg, Org, OrgV; TYPE typedef struct Options_t { inFile: char *; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) ov,oe,of : REF ARRAY OF INTEGER; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { for (i = 0; i < top->cell.ne; i++) { ??? a = Srot(top.cell[i]); ??? top = MakeCellTopology(a); ??? pn = Org(a); { fprintf(stderr, "Cell: " & Fmt.Int(i) & "\n"); fprintf(stderr, " nv : " & Fmt.Int(top.node.ne) & "\n"); fprintf(stderr, " ne : " & Fmt.Int(top.edge.ne) & "\n"); fprintf(stderr, " nf : " & Fmt.Int(top.wall.ne) & "\n"); assert(top.node.ne-top.edge.ne+top.wall.ne==2); fprintf(stderr, " Nodes:\n"); fprintf(stderr, " "); ov = NEW(REF ARRAY OF INTEGER, top.node.ne); for (j = 0; j < top.node.ne; j++) { ??? ver = top.vRef[j]; { assert(Pneg(top.vRef[j]) == pn); ov[j] = OrgV(ver)->num; } } Mis.InsertionSort(top.node.ne-1,ov); for (j = 0; j < top.node.ne; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(ov[j]),2) & " "); } fprintf(stderr, "\n"); oe = NEW(REF ARRAY OF INTEGER, top.edge.ne); for (j = 0; j < top.edge.ne; j++) { ??? eer = top.eRef[j]; { assert(Pneg(top.eRef[j]) == pn); oe[j] = PEdge(eer)->num; } } Mis.InsertionSort(top.edge.ne-1,oe); fprintf(stderr, " @{Edge->?}s:\n"); fprintf(stderr, " "); for (j = 0; j < top.edge.ne; j++) { if (j == 24){ fprintf(stderr, "\n" & " "); } fprintf(stderr, Fmt.Pad(Fmt.Int(oe[j]),2) & " "); } fprintf(stderr, "\n"); of = NEW(REF ARRAY OF INTEGER, top.wall.ne); for (j = 0; j < top.wall.ne; j++) { ??? fer = top.fRef[j]; { assert(Pneg(top.fRef[j]) == pn); of[j] = PWall(fer)->num; } } Mis.InsertionSort(top.wall.ne-1,of); fprintf(stderr, " Walls:\n"); fprintf(stderr, " "); for (j = 0; j < top.wall.ne; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(of[j]),2) & " "); } fprintf(stderr, "\n"); } } return 0; } Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Teste" \ " -inFile " \ "\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } TestePolyTopology. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TriangToGeom.c #define PROG_NAME "TriangToGeom" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TriangToGeom_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Writes an arbitrary topology (triangulation or not) in the OOGL formats "skel" (collections of points and polylines) or "off" (collections of planar polygons with possibly shared nodes. If "all" is present, then writes all walls, else writes only walls with the attribute "exists==TRUE". Revisions: 08-07-2000: Added the silhouette walls. 21-07-2000: More color and opacity index for the silhouette walls. 08-10-2000: Standarized the WriteWall procedures equal to the TriangToX3D module, such don't more use the OrgV()->num information for compute the extremum nodes of the wall. */ // #INCLUDE #include #include #include // #INCLUDE // #INCLUDE // #INCLUDE #include #include // // #INCLUDE // #INCLUDE TYPE double Format = {Skel, Off}; /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ double FourNodes_t = RECORD u, v, w, x: uint; } typedef struct Options_t { char *inFileTp; inFileSt3 : char *; char *outFile; bool_t all; Format format; char *formatName; bool_t silhouette; /*TRUE draws the silhouette walls */ color: frgb_t; /*attributes of color and opacity for silhouette */ REAL opacity; /*walls,Transparent (opacity==1) Opaque (opacity==0)*/ } bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { assert(d!=0.0); if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? rc3 = Tridimensional.ReadState3D(o->inFileSt3); ??? top = tc.top; ??? c3 = rc3^; { if (o->format == Format.Skel) { WriteSkelFile(top, c3, o); } else if (o->format == Format.Off){ WriteOffFile(top, c3, o); } return 0; } void WriteSkelFile(ElemTableRec_t *top, *c3 : Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(o->outFile & ".skel"); { fprintf(wr, "appearance {shading csmooth linewidth 1}\n"); fprintf(wr, "nSKEL 3\n"); WriteSkel(wr, top, c3, o); fclose(wr) } } /* END WriteSkelFile */ void WriteOffFile(ElemTableRec_t *top, *c3 : Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(o->outFile & ".off"); { fprintf(wr, "appearance {shading csmooth linewidth 1}\n"); fprintf(wr, "OFF\n"); WriteOff(wr, top, c3, o); fclose(wr) } } /* END WriteOffFile */ void WriteSkel ( FILE *wr, *ElemTableRec_t *top; *c3 : Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) == double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x compute us its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; void WriteSkelWall( uint *n; *f : Triangulation.Wall; ) /* This procedure writes a n-gon wall */ REF ARRAY OF INTEGER g ; Place_t @p; { ??? vd = digits(top->node.ne-1); { g = NEW(REF ARRAY OF INTEGER, n); fprintf(wr, Fmt.Int(n+1) & " "); a = f.pa; for (i = 0; i < n; i++) { g[i] = OrgV(a)->num; fprintf(wr, Fmt.Pad(Fmt.Int(g[i]), vd) & " "); a = NextE(a); } fprintf(wr, Fmt.Pad(Fmt.Int(g[0]), vd) & " "); fprintf(wr, " 0.00 0.00 0.00 "); /* color */ fprintf(wr, " 1"); /* Index of opacity */ fprintf(wr, "\n"); fflush(wr); } } WriteSkelWall; m: uint = 0; /* number of existing walls */ { for (i = 0; i < top->wall.ne; i++){ if (top->wall[i]->exists){ m++; } } if (o->silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; { if ((SilhouetteWalls(a)) && (NOT f->exists)){ m++; } } } } if (o->all) { fprintf(wr, Fmt.Int(top->node.ne) & " " & Fmt.Int(top->wall.ne) & "\n"); fprintf(wr, "\n"); } else if (! o->silhouette){ fprintf(wr, Fmt.Int(top->node.ne) & " " & Fmt.Int(m) & "\n"); fprintf(wr, "\n"); } else if (o->silhouette){ fprintf(wr, Fmt.Int(top->node.ne) & " " & Fmt.Int(m) & "\n"); fprintf(wr, "\n"); } for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint3D(wr,c3[v->num]); fprintf(wr, "\n"); } } fprintf(wr, "\n"); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if ((o->all) || (top->wall[i]->exists)) { WriteSkelWall(((f.node^).ne),f); } } } if (o->silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WriteSkelWall(Octf.DegreeOfEdge(a),f); } } } } fclose(wr); } /* END WriteSkel */ void WriteOff ( FILE *wr, *ElemTableRec_t *top; *c3: Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) == double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x compute us its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; void WriteOffWall( uint *n; *f : Triangulation.Wall; diffuse : frgb_t; REAL transp; ) /* This procedure writes a {n}-gon wall, associated to the @place wall-@{edge->?} "a" with color "diffuse" and transparency "opacity" */ REF ARRAY OF INTEGER g ; { ??? vd = digits(top->node.ne-1); { g = NEW(REF ARRAY OF INTEGER, n); fprintf(wr, Fmt.Int(n) & " "); for (i = 0; i < n; i++) { g[i] = f.node[i]->num; fprintf(wr, Fmt.Pad(Fmt.Int(g[i]), vd) & " "); } Mis.WriteColor(wr,diffuse); fprintf(wr, " "); Mis.WriteIntensity(wr,transp); fprintf(wr, "\n"); fflush(wr); } } WriteOffWall; m: uint = 0; /* number of existing walls */ { for (i = 0; i < top->wall.ne; i++){ if (top->wall[i]->exists){ m++; } } if (o->silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; { if ((SilhouetteWalls(a)) && (NOT f->exists)){ m++; } } } } if (o->all) { fprintf(wr, Fmt.Int(top->node.ne) & " " & Fmt.Int(top->wall.ne) & " " \ Fmt.Int(top->NE) & "\n"); fprintf(wr, "\n"); } else if (! o->silhouette){ fprintf(wr, Fmt.Int(top->node.ne) & " " & Fmt.Int(m) & " " \ Fmt.Int(top->NE) & "\n"); fprintf(wr, "\n"); } else if (o->silhouette){ fprintf(wr, Fmt.Int(top->node.ne) & " " & Fmt.Int(m) & " " \ Fmt.Int(top->NE) & "\n"); fprintf(wr, "\n"); } for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { Mis.WritePoint3D(wr,c3[v->num]); fprintf(wr,"\n"); } } fprintf(wr, "\n"); for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? fc = f.color; ??? t3 = f.transp; ??? tp = (t3[0] + t3[1] + t3[2]) / 3.0; { if ((o->all) || (top->wall[i]->exists)) { WriteOffWall(((f.node^).ne),f,fc,tp); } } } if (o->silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; ??? c = o->color; ??? t = o->opacity; { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WriteOffWall(((f.node^).ne),f,c,t); } } } } fclose(wr); } /* END WriteOff */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt3"); o->inFileSt3 = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } o->all = argparser_keyword_present(pp, "-all"); argparser_get_keyword(pp, "-format"); o->formatName = argparser_get_next(pp); if (0 == strcmp(o->formatName, "skel"))) { o->format = Format.Skel } else if (0 == strcmp(o->formatName, "off"))){ o->format = Format.Off } else { argparser_error(pp, "Bad format \"" & argparser_get_next(pp) & "\"\n") } if ((argparser_keyword_present(pp, "-silhouette"))) { o->silhouette = TRUE; if ((argparser_keyword_present(pp, "-color"))) { for (j = 0; j < 3; j++) { o->color[j] = pp.getNextReal(0.0,1.0); } } else { o->color = (frgb_t){1.0,1.0,0.75}; } if ((argparser_keyword_present(pp, "-opacity"))) { o->opacity = pp.getNextReal(0.0,1.0); } else { o->opacity = 0.85; } } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr,"Usage: TriangToGeom \\\n"); fprintf(stderr," -inFileTp -inFileSt3 \\\n"); fprintf(stderr," [-outFile ] [-all] \\\n"); fprintf(stderr," -format { skel | off }\n"); fprintf(stderr," [ -silhouette [ -color | -opacity ] ]\n"); END¦ } } return o; } /* END GetOptions */ /* end TriangToGeom */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TriangToPov.c #define PROG_NAME "TriangToPov" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TriangToPov_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program contain procedures to write configurations "3D" in POVray format (".inc").. */ #include #include #include // #INCLUDE // #INCLUDE #include #include // // #INCLUDE // NextF, NextE, Clock; // #INCLUDE // #INCLUDE // #INCLUDE TYPE double bool_t = bool_t; double NAT = uint; double WallNums = ARRAY OF NAT; TYPE typedef struct Options_t { char *inFileTp; inFileSt3: char *; char *outFile; bool_t all; /* TRUE draws even non-existing triangles and edges. */ walls: REF WallNums; /* List of walls to show (NULL == all). */ styles: REF StyleSpecs; /* Styles for various classes of elements. */ bool_t debug; /* Print style info for all elements. */ } TYPE double ElemDim = [0..4]; /* Element dimension; "4" means "ANY". */ CONST AnyDim == 4; TYPE double ElemType = BITS 32 for (RECORD dim: BITS 8 for (ElemDim; /* Dimension of element. */ momDim: BITS 8 for (ElemDim; /* Dimension of mother element. */ bdr: BITS 1 for (bool_t = FALSE; /* Element is part of the map's border. */ sil: BITS 1 for (bool_t = FALSE; /* Element is part of silhouette surface. */ mwr: BITS 1 for (bool_t = FALSE; /* Element is miswrapped node. */ mwn: BITS 1 for (bool_t = FALSE; /* Element is part of miswound @{edge->?}. */ } double ElemTypes = ARRAY OF ElemType; double AllElementTypes = RECORD vType: REF ElemTypes; /* Indexed by node number. */ eType: REF ElemTypes; /* Indexed by @{edge->?} number. */ fType: REF ElemTypes; /* Indexed by wall number. */ pType: REF ElemTypes; /* Indexed by cell number. */ } TYPE double ElemStyle = RECORD /* Style attributes for walls. */ bool_t textured; /* TRUE for textured wall, FALSE for solid color. */ REAL radius; /* Radius (for edges or nodes). */ frgb_t color; /* Color of element. */ REAL transp; /* Transp (1==clear, 0==opaque). */ bool_t filtering; /* TRUE for "filter" transparency, FALSE for "transmit". */ } TYPE double StyleSpec = RECORD /* Style specs for elements of a certain type */ typ: ElemType; /* Type of elements to which this style applies. */ sty: ElemStyle; /* Style to use for elements of this dimension and type. */ } double StyleSpecs = ARRAY OF StyleSpec; /* Style specs in decr. priority order. */ /* Let "e" be an element of the model, of dimension "e.dim" and belonging to a map element of dimension "e.momDim". To show this element, the "StyleSpecs" list is searched until an entry "t" has "t.typ.dim == e.dim", "t.typ.momDim == e.momDim", "t.typ.xxx <= e.xxx" for every other boolean attribute ("bdr", "sil", "mwn", and "mwr"). Thus specs for non-border, non-silhouette elements must follow those of border and/or silhouette ones. In StyleSpec records, the following conventions hold: positive color, transparency, and radius values are absolute, while negative ones (after change of sign) multiply the original values specified in the map files. Thus color == (1,1,1) means set color to white, while (-1,-1,-1) means keep the original color. In particulas, a wall can be made invisible by specifying double color = (1,1,1) and transp == 1; and edges and nodes can be made invisible by specifying radius == 0. */ CONST White == (frgb_t){1.0, 1.0, 1.0}; Black == (frgb_t){0.0, 0.0, 0.0}; double Clear = 1.0; double Opaque = 0.0; double OriginalColor = (frgb_t){-1.0, -1.0, -1.0}; double OriginalTransp = -1.0; double OriginalRadius = -1.0; CONST double OriginalElemStyle = ElemStyle { textured = FALSE, radius = OriginalRadius, color = OriginalColor, transp = OriginalTransp, filtering = FALSE }; Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? rc3 = Tridimensional.ReadState3D(o->inFileSt3); ??? top = tc.top; ??? c3 = rc3^; ??? atp = ComputeAllElementTypes(top; with (c3) ){ if (o->walls!=NULL){ RemoveElements(tc.top, o->walls^); } WritePOVFile(top, c3, atp, o); return 0; } AllElementTypes ComputeAllElementTypes(ElemTableRec_t *top, *c3: Coords3D_t; ) CONST double VVType = ElemType{dim = 0, momDim = 0}; double VEType = ElemType{dim = 0, momDim = 1}; double VFType = ElemType{dim = 0, momDim = 2}; double VPType = ElemType{dim = 0, momDim = 3}; double EEType = ElemType{dim = 1, momDim = 1}; double EPType = ElemType{dim = 1, momDim = 3}; double FFType = ElemType{dim = 2, momDim = 2}; double FPType = ElemType{dim = 2, momDim = 3}; double PPType = ElemType{dim = 3, momDim = 3}; atp: AllElementTypes; { /* Initialize everybody as PType */ atp.vType = NEW(REF ElemTypes, top->node.ne); atp.eType = NEW(REF ElemTypes, top->NE); atp.fType = NEW(REF ElemTypes, top->wall.ne); atp.pType = NEW(REF ElemTypes, top->cell.ne); /* Mark nodes according to container in the original map, and wrapping number: */ ??? vtp = atp.vType^; { for (i = 0 TO (vtp.ne-1)) { Node_t vi = OrgV(top->node[i]); { if (0 == strcmp(vi.label, "VV"))) { vtp[i] = VVType } else if (0 == strcmp(vi.label, "VE"))){ vtp[i] = VEType } else if (0 == strcmp(vi.label, "VF"))){ vtp[i] = VFType } else if (0 == strcmp(vi.label, "VP"))){ vtp[i] = VPType } else { assert(FALSE); } if ((fabs(NodeWrappingNumber(top->node[i], c3))!=1)){ vtp[i].mwr = TRUE; } } } } /* Mark @{edge->?}s of original map, and m-fold @{edge->?}s: */ ??? etp = atp.eType^; { for (i = 0 TO (etp.ne-1)) { ??? ei = top->edge[i]; { if (ei->root!=-1) { etp[i] = EEType } else { etp[i] = EPType /* For now */ } if ((fabs(EdgeWindingNumber(top->edge[i].pa, c3))!=1)) { etp[i].mwn = TRUE } } } } /* Mark walls of the original map, border walls, and silhouette walls: */ ??? ftp = atp.fType^; { for (i = 0 TO (ftp.ne-1)) { ??? fi = top->wall[i], ftpi == ftp[i]; { if (fi->root!=-1) { ftpi = FFType } else { ftpi = FPType } if ((WallIsBorder(fi.pa))){ ftpi.bdr = TRUE; } if ((WallIsSilhouette(fi.pa, c3))){ ftpi.sil = TRUE; } } } } /* Mark cells of original map (all of them): */ ??? ptp = atp.pType^; { for (i = 0 TO (ptp.ne-1)){ ptp[i] = PPType;} } /* Propagate attributes from walls to @{edge->?}s, and fix @{edge->?} "momDim"s: */ ??? ftp = atp.fType^, etp == atp.eType^; { for (i = 0 TO (ftp.ne-1)) { ??? fi = top->wall[i], ftpi == ftp[i]; { assert(ftpi.dim == 2); assert(ftpi.momDim >= 2); /* Enumerate bounding @{edge->?}s: */ VAR a = fi.pa; b = a; { do { ??? eb = PEdge(b), ebtp == etp[eb->num]; { /* Fix @{edge->?}'s "momDim": */ if ((ebtp.momDim == 3) && (ftpi.momDim == 2)) { /* @{Edge->?}'s mom was not an @{edge->?}, so it must be the wall's mom: */ ebtp.momDim = 2 } /* Propagate border attributes: */ ebtp.bdr = ebtp.bdr) || (ftpi.bdr; /* Propagate silhouette attribute: */ ebtp.sil = ebtp.sil) || (ftpi.sil; assert(ebtp.momDim <= ftpi.momDim); } b = NextE(b) } while (b != a); } } } } /* Propagate attributes from @{edge->?} to node ("momDim"s should be OK): */ ??? etp = atp.eType^, vtp == atp.vType^; { for (i = 0 TO (etp.ne-1)) { ??? ei = top->edge[i], etpi == etp[i]; { assert(etpi.dim == 1); assert(etpi.momDim >= 1); /* Enumerate endpoints: */ Node_t v0 = OrgV(ei.pa); with ( v1 == OrgV(Clock(ei.pa)), double v = ARRAY [0..1] OF Node{v0, v1} ){ for (i = 0; i < 2; i++) { ??? vi = v[i], vitp == vtp[vi->num]; { assert(vitp.momDim <= etpi.momDim); /* Propagate border, silhouette, miswound attributes: */ vitp.bdr = vitp.bdr) || (etpi.bdr; vitp.sil = vitp.sil) || (etpi.sil; vitp.mwn = vitp.mwn) || (etpi.mwn; } } } } } } return atp; } /* END ComputeAllElementTypes */ PROCEDURE RemoveElements(ElemTableRec_t *top, *walls: WallNums) /* Marks all nodes, @{edge->?}s, and walls of "top" as non-existing, except those that are incident to one of the specified walls of the original map. Assumes that cells are invisible in any case. */ { /* Remove all @{edge->?}s and nodes: */ for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { v->exists = FALSE; } } for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { e->exists = FALSE; } } /* Put back @{edge->?}s and nodes of interesting walls, remove non-interesting ones: */ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists) { if ((WallIsSelected(f, walls))) { VAR Place_t @p = f.pa; Place_t b = a; VAR { do { OrgV(b)->exists = TRUE; PEdge(b)->exists = TRUE; b = NextE(b) } while (b != a); } } else { f->exists = FALSE } } } } } /* END RemoveElements */ bool_t WallIsSelected(f: Wall; *walls: WallNums) /* Returns TRUE if the wall "f" is part of one of the specified walls of the original map. */ { if (f->root == -1){ return FALSE; } else { for (k = 0 TO (walls.ne-1)) { if (f->root == walls[k]){ return TRUE;} } return FALSE } } /* END WallIsSelected */ void WritePOVFile(ElemTableRec_t *top, * c3: Coords3D_t; *atp: AllElementTypes; Options_t * o; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? name = o->outFile & ".inc"; ??? wr = FileWr.Open(name); { fprintf(stderr, "writing " & name & "\n"); fprintf(wr, "// Include File: <" & o->outFile & ".inc>\n"); WritePOV(wr, top, c3, atp, o); fclose(wr) } } /* END WritePOVFile */ void WritePOV( FILE *wr, *ElemTableRec_t *top; * c3: Coords3D_t; *atp: AllElementTypes; Options_t * o; ) void WriteElemComment(txt: char *; num: INTEGER) { fprintf(wr, " // "); fprintf(wr, txt); fprintf(wr, " "); fprintf(wr, Fmt.Int(num)); fprintf(wr, "\n"); } WriteElemComment; void WriteWall(f: Wall; *fs: ElemStyle) /* Writes the POV representation of "f". */ void WriteTriangle(Place_t @p) /* Writes the POV representation of "a.wall", which is assumed to be a triangle. */ { Place_t b = NextE(a); Place_t c = NextE(b); Node_t un = OrgV(a)->num; Node_t vn = OrgV(b)->num; Node_t wn = OrgV(c)->num; { if (fs.textured) { ??? txName = "wall_texture_" & Fmt.Pad(Fmt.Int(PWall(a)->num),6,'0'); { WritePOVTriangleTex(wr, c3[un], c3[vn], c3[wn], txName) } } else { WritePOVTriangle(wr,c3[un],c3[vn],c3[wn], fs.color, fs.transp, fs.filtering); } } } WriteTriangle; void WritePolygon(Place_t @p) /* Writes the POV representation of "a.wall", which is assumed to be a non-planar N-gon. */ VAR Place_t c; bar: r3_t = (r3_t){0.0, ..}; ne: NAT = 0; { c = a; do { Node_t k = OrgV(c)->num; { bar = r3_add(bar, c3[k]); } c = NextE(c); ne++; } while (c != a); bar = r3_scale(1.0/FLOAT(ne,double), bar); c = a; do { Node_t un = OrgV(c)->num; Node_t vn = OrgV(Clock(c))->num; { if (fs.textured) { ??? txName = "wall_texture_" & Fmt.Pad(Fmt.Int(PWall(a)->num),6,'0'); { WritePOVTriangleTex(wr,c3[un],c3[vn],bar, txName) } } else { WritePOVTriangle(wr,c3[un],c3[vn],bar, fs.color, fs.transp, fs.filtering); } } c = NextE(c) } while (c != a); } WritePolygon; { if ((fs.color!=White) || (fs.transp!=Clear)) { ??? a = f.pa; { WriteElemComment("wall", f->num); if ((NextE(NextE(NextE(a))) == a)) { WriteTriangle(a) } else { WritePolygon(a) } } } } WriteWall; PROCEDURE Write@{Edge->?}(e: @{Edge->?}; *es: ElemStyle) == { if (es.radius!=0.0) { ??? a = e.pa; Place_t b = NextE(a); Node_t un = OrgV(a)->num; Node_t vn = OrgV(b)->num; { WriteElemComment("@{edge->?}", e->num); WritePOVCylinder(wr, c3[un], c3[vn], es.radius, es.color, es.transp, es.filtering) } } } Write@{Edge->?}; void WriteNode(Node_t v; *vs: ElemStyle) { if (vs.radius!=0.0) { ??? vn = v->num; { WriteElemComment("node", v->num); WritePOVSphere(wr, c3[vn], vs.radius, vs.color, vs.transp, vs.filtering) } } } WriteNode; { /* Draw nodes */ for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { if ((v->exists) || (o->all)) { ??? vs = GetNodeStyle(v, atp.vType[i], o->styles^, o->debug); { WriteNode(v, vs) } } } } /* Draw @{edge->?}s */ for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { if ((e->exists) || (o->all)) { ??? es = Get@{Edge->?}Style(e, atp.eType[i], o->styles^, o->debug); { Write@{Edge->?}(e, es) } } } } /* Draw walls */ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if ((f->exists) || (o->all)) { ??? fs = GetWallStyle(f, atp.fType[i], o->styles^, o->debug); { WriteWall(f, fs) } } } } fflush(wr); } /* END WritePOV */ ElemStyle GetNodeStyle(Node_t v; tp: ElemType; *sty: StyleSpecs; bool_t db) { ??? s = GetElemStyle(sty, tp, v.radius, v.color, v.transp); { if (db){ DebugStyle("node", v->num, s); } return s; } } /* END GetNodeStyle */ ElemStyle Get@{Edge->?}Style(e: @{Edge->?}; tp: ElemType; *sty: StyleSpecs; bool_t db) { ??? s = GetElemStyle(sty, tp, e.radius, e.color, e.transp); { if (db){ DebugStyle("@{edge->?}", e->num, s); } return s; } } /* END Get@{Edge->?}Style */ ElemStyle GetWallStyle(f: Wall; tp: ElemType; *sty: StyleSpecs; bool_t db) { ??? s = GetElemStyle(sty, tp, 0.0, f.color, f.transp); { if (db){ DebugStyle("wall", f->num, s); } return s; } } /* END GetWallStyle */ PROCEDURE DebugStyle(elName: char *; elNum: NAT; s: ElemStyle) { fprintf(stderr, elName & " " & Fmt.Int(elNum)); fprintf(stderr, " style == " & FStyle(s) & "\n"); } /* END DebugStyle */ PROCEDURE FStyle(s: ElemStyle): char *== { return "{" \ "textured = " & FBool(s.textured) & ", " \ "radius = " & Fmt.Real(s.radius) & ", " \ "color = " & FColor(s.color) & ", " \ "transp = " & Fmt.Real(s.transp) & ", " \ "filtering = " & FBool(s.filtering) & "}" } /* END FStyle */ PROCEDURE FBool(bool_t x): char *== { if (x){ return "T" }else{ return "F"; } } /* END FBool */ PROCEDURE FColor(x: frgb_t): char *== { return "(" \ Fmt.Real(x[0], prec = 4, style = Fmt.Style.Fix) & "," \ Fmt.Real(x[1], prec = 4, style = Fmt.Style.Fix) & "," \ Fmt.Real(x[2], prec = 4, style = Fmt.Style.Fix) & ")" } /* END FColor */ ElemStyle GetElemStyle( *sty: StyleSpecs; tp: ElemType; REAL radius; frgb_t color; transp3: frgb_t; ) { ??? transp = (transp3[0] + transp3[1] + transp3[2]) / 3.0; { for (i = 0 TO (sty.ne-1)) { ??? si = sty[i]; { if ((tp.dim == si.typ.dim ) && ((tp.momDim == si.typ.momDim) || (si.typ.momDim == AnyDim) ) && (tp.bdr >= si.typ.bdr ) && (tp.sil >= si.typ.sil ) && (tp.mwn >= si.typ.mwn ) && (tp.mwr >= si.typ.mwr )){ ??? s = si.sty; { return ElemStyle { textured = s.textured, radius = ModifyRadius(radius, s.radius), color = ModifyColor(color, s.color), transp = ModifyTransp(transp, s.transp), filtering = s.filtering } } } } } return ElemStyle { textured = FALSE, radius = radius, color = color, transp = transp, filtering = TRUE } } } /* END GetElemStyle */ <*UNUSED); PROCEDURE @{Edge->?}ContainedInMapWall(Place_t @p): bool_t == /* Return TRUE if the edge associated to the @place "a" belongs to an existing wall of the map. Return FALSE c.c. */ Place_t b = a; { do { with (f == PWall(b)) { if (f->root!=-1){ return TRUE;} } b = NextF(b); } while (b != a); return FALSE; } /* END @{Edge->?}ContainedInMapWall */ PROCEDURE NodeWrappingNumber( <*UNUSED); Place_t @p; <*UNUSED); *c3: Coords3D_t ): INTEGER == /* Computes the wrapping number of the node "OrgV(a)". */ { return 1 /* For now... */; } /* END NodeWrappingNumber */ frgb_t ModifyColor(*orig, opt: frgb_t) /* Combines an option-specified color with the intrinsic one. */ c: frgb_t; { for (i = 0; i < 3; i++){ if (opt[i] > 0.0) { c[i] = MIN(1.0, opt[i]) } else { c[i] = MAX(0.0, MIN(1.0, fabs(opt[i])*orig[i])) } } return c; } /* END ModifyColor */ REAL ModifyTransp(*orig, opt: REAL) /* Combines an option-specified transparency with the intrinsic one. */ { if (opt > 0.0){ return MIN(1.0, opt); } else { return MAX(0.0, MIN(1.0, fabs(opt) * orig)); } } /* END ModifyTransp */ REAL ModifyRadius(*orig, opt: REAL) /* Combines an option-specified radius with the intrinsic one. */ { if (opt > 0.0){ return opt; } else { return MAX(0.0, fabs(opt) * orig); } } /* END ModifyRadius */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt3"); o->inFileSt3 = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } if ((argparser_keyword_present(pp, "-all"))) { o->all = TRUE; o->walls = NULL } else if ((argparser_keyword_present(pp, "-walls"))){ o->all = FALSE; o->walls = ParseWallNums(argparser_get_next(pp)) } else { o->all = FALSE; o->walls = NULL } o->debug = argparser_keyword_present(pp, "-debug"); VAR styles = NEW(REF StyleSpecs, 10); nStyles: NAT = 0; { while (argparser_keyword_present(pp, "-style")) { if ((! pp.testNext("of"))){ argparser_error(pp, "\"of\" expected"); } ??? dim = ParseElemDimension(pp); { while (pp.testNext("if")) { if ((nStyles >= ((styles^).ne))) { ??? ns = NEW(REF StyleSpecs, 2*nStyles + 10); { SUBARRAY(ns^,0,nStyles) = styles^; styles = ns } } styles[nStyles] = ParseStyleSpec(pp, dim); nStyles++; } } } o->styles = NEW(REF StyleSpecs, nStyles); o->styles^ = SUBARRAY(styles^, 0, nStyles) } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr,"Usage: TriangToPov \\\n"); fprintf(stderr," -inFileTp -inFileSt3 \\\n"); fprintf(stderr," [ -outFile ] \\\n"); fprintf(stderr," [ -all | -walls ,,..., ] \\\n"); fprintf(stderr," [ -debug ] \\\n"); fprintf(stderr," [ -style of { walls | @{edge->?}s | nodes } \\\n"); fprintf(stderr," [ if [ border | silhouette | miswound | miswrapped | \\\n"); fprintf(stderr," from { nodes | @{edge->?}s | walls | cells } ]... \\\n"); fprintf(stderr," then \\\n"); fprintf(stderr," [ invisible | textured | \\\n"); fprintf(stderr," [ radius [==|×] ] \\\n"); fprintf(stderr," [ color [==|×] ] \\\n"); fprintf(stderr," [ {transmit | filter} [==|×] ] \\\n"); fprintf(stderr," \\\n"); fprintf(stderr," ]... \\\n"); fprintf(stderr," ]...\n"); fprintf(stderr," ]...\n"); END¦ } } return o; } /* END GetOptions */ StyleSpec PROCEDURE ParseStyleSpec( argparser_t *pp; ElemDim dim; )/* Raises {ParseParams.Error} */ == s = StyleSpec { typ = ElemType{dim = dim, momDim = AnyDim}, sty = OriginalElemStyle }; { s.typ.bdr = FALSE; s.typ.sil = FALSE; s.typ.mwn = FALSE; s.typ.mwr = FALSE; while (1) { if ((pp.testNext("border"))) { s.typ.bdr = TRUE } else if ((pp.testNext("silhouette"))){ s.typ.sil = TRUE } else if ((pp.testNext("miswound"))){ s.typ.mwn = TRUE } else if ((pp.testNext("miswrapped"))){ s.typ.mwr = TRUE } else if ((pp.testNext("from"))){ if ((! pp.testNext("map"))){ argparser_error(pp, "\"map\" expected"); } s.typ.momDim = ParseElemDimension(pp); } else { EXIT } } if ((! pp.testNext("then"))){ argparser_error(pp, "\"then\" expected"); } s.sty = ParseElemStyle(pp); if (dim > s.typ.momDim) { argparser_error(pp, "invalid mom/child dimensions") } return s; } /* END ParseStyleSpec */ ElemDim PROCEDURE ParseElemDimension(argparser_t *pp)/* Raises {ParseParams.Error} */ { if ((pp.testNext("cells"))){ return 3; } else if ((pp.testNext("walls"))){ return 2; } else if ((pp.testNext("@{edge->?}s"))){ return 1; } else if ((pp.testNext("nodes"))){ return 0; } else { argparser_error(pp, "bad original map element"); assert(FALSE); } } /* END ParseElemDimension */ ElemStyle PROCEDURE ParseElemStyle(argparser_t *pp)/* Raises {ParseParams.Error} */ == s: ElemStyle = OriginalElemStyle; { if ((pp.testNext("invisible"))){ s.textured = FALSE; s.radius = 0.0; s.color = White; s.transp = Clear; } else if ((pp.testNext("textured"))){ s.textured = TRUE; s.color = Black; s.transp = Opaque; } else { s.textured = FALSE; while (1) { if ((pp.testNext("radius"))) { ??? negate = ParseOptionalMulOp(pp); { s.radius = pp.getNextReal(0.0, 100.0); if (negate){ s.radius = - s.radius;} } } else if ((pp.testNext("color"))){ ??? negate = ParseOptionalMulOp(pp); { for (j = 0; j < 3; j++) { s.color[j] = pp.getNextReal(0.0,100.0); if (negate){ s.color[j] = -s.color[j]; } } } } else if ((pp.testNext("transmit"))){ s.filtering = FALSE; ??? negate = ParseOptionalMulOp(pp); { s.transp = pp.getNextReal(0.0,100.0); if (negate){ s.transp = - s.transp;} } } else if ((pp.testNext("filter"))){ s.filtering = TRUE; ??? negate = ParseOptionalMulOp(pp); { s.transp = pp.getNextReal(0.0,100.0); if (negate){ s.transp = - s.transp;} } } else { EXIT } } } return s; } /* END ParseElemStyle */ bool_t ParseOptionalMulOp(argparser_t *pp) /* Parses an optional "==" or "×", returns TRUE if "×". */ { if ((pp.testNext("=="))){ return FALSE; } else if ((pp.testNext("×"))){ return TRUE; } else { return FALSE; } } /* END ParseOptionalMulOp */ PROCEDURE ParseWallNums(txt: char *): REF WallNums/* Raises {ParseParams.Error} */ == NAT i, j, k; c: REF WallNums = NEW(REF WallNums, 10); { ¦TRY ??? n = Text.Length(txt); { i = 0; k = 0; while (i < n) { j = i+1; while (j < n) && (Text.GetChar(txt,j)!=','){ j++; } if ((c == NULL) || (k >= ((c^).ne))) { ??? cNew = NEW(REF WallNums, 2*k); { if (c != NULL){ SUBARRAY(cNew^, 0, k) = c^; } c = cNew; } } ??? tn = Text.Sub(txt,i,j-i); { c[k] = Scan.Int(tn); } k++; i = j+1; } if (c == NULL) { return NULL; } else { ??? cTrim = NEW(REF WallNums, k); { cTrim^ = SUBARRAY(c^, 0, k); return cTrim; } } } EXCEPT Lex.Error, FloatMode.Trap ==> RAISE ParseParams.Error; } } /* END ParseWallNums */ /* end TriangToPov */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TriangToWire4.c #define PROG_NAME "TriangToWire4" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TriangToWire4_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This module writes the configuration as expected by the "Wire4" - Interactive 4D Wireframe Display program (".w4"). */ #define TriangToWire4_C_author \ "Created by L.A.P.Lozada, 1999-2000.\n" \ "Revisions:\n" \ " 08-07-2000: Added the silhouette walls. Note that the silhouette walls\n" \ " depending of the 4D->3D projection, so for any 3D rotation\n" \ " the silhouette walls are the same. But for any 4D rotation\n" \ " the 3D projection changes and consequently the silhouette\n" \ " walls also change.\n" \ " 07-08-2000: Included the {normalization} option by Stolfi.\n" \ " 04-11-2000: Last modification by Lozada.\n" \ #include // #INCLUDE #include #include // #INCLUDE #include #include // #INCLUDE // #INCLUDE #include //#include CONST double INIT_STACK_SIZE = 100000; double Epsilon = 0.0000000001; VAR nee,nfe: uint = 0; /* number of @{edge->?}s and walls existing */ estack = NEW(REF uint_vec_t , INIT_STACK_SIZE); /* stack for edges */ etop : uint = 0; /* top for the above stacks */ Color palette[5+1]; /* the palette colors for the original walls. */ fac : REF ARRAY OF Color; /* the wall colors to use */ /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ TYPE double Row3I = ARRAY [0..2] OF INTEGER; double Color = frgb_t; FourNodes_t == RECORD u, v, w, x: uint; } double PACK = RECORD bool_t belong; num: INTEGER; } typedef struct Options_t { char *inFileTp; char *inFileSt; char *outFile; double normalize; /* Normalize al nodes onto the S^3 with that radius. */ From4: r4_t; To4: r4_t; Up4: r4_t; Over4: r4_t; Vangle4: double; From3: r3_t; To3: r3_t; Up3: r3_t; Vangle3: double; INTEGER DepthCueLevels; bool_t all; bool_t silhouette; char *projectionName; bool_t colored; /* coloring the original walls with a defined palete */ uint ordernet; /* Order on the net for original walls of the map. */ } void WriteColor(FILE *wr, *c: Row3I) /* Write colors in RGB mode */ { Mis.WriteInt(wr,c[0]); fprintf(wr," "); Mis.WriteInt(wr,c[1]); fprintf(wr," "); Mis.WriteInt(wr,c[2]); } /* END WriteColor */ PROCEDURE @{Edge->?}BelongsToOriginalWall(Place_t @p, ElemTableRec_t *top): PACK == /* Returns TRUE if the edge component of "a" belongs to a wall of the original map also accomplish the number of the original wall. */ VAR Place_t b = a; PACK pack; { if ((top->edge[PEdge(a)->num]->root!=-1)){ pack.belong = FALSE; pack->num = -1; return pack; } /* Check if any wall incident to "a" belongs to a wall of the original map. */ do { if ((top->wall[PWall(b)->num]->root!=-1)) { pack.belong = TRUE; pack->num = PWall(b)->num; return pack; } b = NextF(b) } while (b != a); pack.belong = FALSE; pack->num = -1; return pack; } /* END @{Edge->?}BelongsToOriginalWall */ bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { assert(d!=0.0); if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) <* FATAL Wr.Failure, Thread.Alerted); { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFileSt); ??? rc3 = NEW(REF Tridimensional.Coords3D_t; with (top->node.ne), c == rc^, c3 == rc3^, double cmt = tc.cmt & "\n Make by TriangToWire4: " & o->outFile \ ".w4 on " & Today() & "\n" ){ if (o->normalize > 0.0) { fprintf(stderr, "projecting nodes onto the unit S^3\n"); NormalizeNodeCoords(c, o->normalize); } ProjectTo3D(o, c, c3, top); WriteWire4File(o, top, c, c3, cmt); return 0; } PROCEDURE NormalizeNodeCoords(VAR c: Coords_t; newR: double) { ??? b = Barycenter(c); { for (i = 0 TO (c.ne-1)) { ??? p = c[i], q == r4_Sub(p, b), r == r4_Norm(q); { if (r > 0.0){ p = r4_Scale(newR/r, q);} } } } } /* END NormalizeNodeCoords */ r4_t Barycenter(*c: Coords_t) B: r4_t = (r4_t){0.0, ..}; { for (i = 0 TO (c.ne-1)){ B = r4_Add(B, c[i]); } return r4_Scale(1.0/FLOAT((c.ne), double), B); } /* END Barycenter */ void WriteWire4File( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); *ElemTableRec_t *top; *c : Triangulation.Coords_t; *c3 : Tridimensional.Coords3D_t; char *cmt; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(o->outFile & ".w4"); { int ind = 0; /* Comment indentation. */ filefmt_write_comment(wr,cmt,ind,'#'); fprintf(wr, "\n"); WriteWire4(o, wr, top, c, c3); fclose(wr) } } /* END WriteWire4File */ void WriteWire4( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); wr: Wr.T; *ElemTableRec_t *top; Coords_t *c; *c3 : Tridimensional.Coords3D_t; ) double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x compute us its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; cv, ce: Row3I; { void WriteCoord(double x) { fprintf(wr, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 4), 7)); } WriteCoord; void WritePoint4D(*c: r4_t) { WriteCoord(c[0]); fprintf(wr, " "); WriteCoord(c[1]); fprintf(wr, " "); WriteCoord(c[2]); fprintf(wr, " "); WriteCoord(c[3]); } WritePoint4D; void WritePoint3D(*c: r3_t) { WriteCoord(c[0]); fprintf(wr, " "); WriteCoord(c[1]); fprintf(wr, " "); WriteCoord(c[2]); } WritePoint3D; { int NV = top->node.ne; ??? NE = top->NE; int NF = top->wall.ne; ??? eWidth = digits(NE-1); { fprintf(wr,"\nDepthCueLevels "); Mis.WriteInt(wr,o->DepthCueLevels); fprintf(wr,"\n"); fprintf(wr, "\nFrom4: "); WritePoint4D(o->From4); fprintf(wr, "\nTo4 : "); WritePoint4D(o->To4); fprintf(wr, "\nUp4 : "); WritePoint4D(o->Up4); fprintf(wr, "\nOver4: "); WritePoint4D(o->Over4); fprintf(wr, "\nVangle4: "); Mis.WriteLong(wr, o->Vangle4); fprintf(wr, "\n"); fprintf(wr, "\nFrom3: "); WritePoint3D(o->From3); fprintf(wr, "\nTo3 : "); WritePoint3D(o->To3); fprintf(wr, "\nUp3 : "); WritePoint3D(o->Up3); fprintf(wr, "\nVangle3: "); Mis.WriteLong(wr, o->Vangle3); fprintf(wr, "\n"); if (0 == strcmp(o->projectionName,"Perspective"))) { fprintf(wr, "\nProject4: Perspective"); } else { fprintf(wr, "\nProject4: Parallel"); } /* nodes */ fprintf(wr, "\n\nNodeList " & Fmt.Int(NV) & ":\n"); for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); { WritePoint4D(c[v->num]); fprintf(wr, " : "); cv[0] = ROUND(v.color[0]*255.0); cv[1] = ROUND(v.color[1]*255.0); cv[2] = ROUND(v.color[2]*255.0); WriteColor(wr, cv); fprintf(wr, " : "); Mis.WriteRadius(wr, v.radius); fprintf(wr, "\n"); } } fprintf(wr, "\n"); /* @{EDGE->?}S */ for (i = 0; i < NE; i++) { ??? e = top->edge[i]; { if ((e->exists) || (o->all)){ nee++;} } } for (i = 0; i < NF; i++) { ??? f = top->wall[i]; { if ((f->exists) || (o->all)){ nfe++;} } } if (o->colored) { /* computing the original number walls */ uint max = 0; { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists) { max = MAX(max,f->root); } } } fprintf(stderr,"The original number walls is " & Fmt.Int(max+1) & "\n"); fac = NEW(REF ARRAY OF Color,max+1); /* defining the palette colors with brightness aprox. 0.7 */ palette[0] = Color{1.00,0.50,1.00}; palette[1] = Color{0.00,1.00,1.00}; palette[2] = Color{0.80,0.80,0.00}; palette[3] = Color{1.00,0.60,0.60}; palette[4] = Color{0.25,1.00,0.25}; palette[5] = Color{0.70,0.70,1.00}; /* attribution of differents colors for each original wall */ for (j = 0; j <= (max); j++) { fac[j] = palette[j % 6]; } } }; if (o->silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; with (aen == PEdge(a)->num, b == NextE(a), ben == PEdge(b)->num, c == PrevE(a), cen == PEdge(c)->num ){ if ((SilhouetteWalls(a))) { if ((! Present(estack, etop, aen))) { nee++; Save(estack,etop,aen); } if ((! Present(estack, etop, ben))) { nee++; Save(estack,etop,ben); } if ((! Present(estack, etop, cen))) { nee++; Save(estack,etop,cen); } } } } } /* Clean the stack */ while (etop > 0) { etop = etop - 1; estack.e[etop] = 0; } fprintf(wr, "@{Edge->?}List " & Fmt.Int(nee) & ":\n"); for (i = 0; i < NE; i++) { ??? e = top->edge[i]; ??? a = e.pa; { if ((e->exists) || (o->all)) { fprintf(wr, Fmt.Pad(Fmt.Int(OrgV(a)->num), eWidth) & " " \ Fmt.Pad(Fmt.Int(OrgV(Clock(a))->num), eWidth)); fprintf(wr, " : "); /* color */ if (! o->colored) { ce[0] = ROUND(e.color[0]*255.0); ce[1] = ROUND(e.color[1]*255.0); ce[2] = ROUND(e.color[2]*255.0); } if (o->colored) { if ((e->exists) && (@{Edge->?}BelongsToOriginalWall(a,top).belong)) { /* is an @{edge->?} on the net belonging to some original wall */ ??? facc = @{Edge->?}BelongsToOriginalWall(a; with (top)->num, double froot = top->wall[facc]->root ){ ce[0] = ROUND(fac[froot][0]*255.0); ce[1] = ROUND(fac[froot][1]*255.0); ce[2] = ROUND(fac[froot][2]*255.0); } } else if ((e->exists) && (NOT @{Edge->?}BelongsToOriginalWall(a,top).belong)){ ce[0] = ROUND(e.color[0]*255.0); ce[1] = ROUND(e.color[1]*255.0); ce[2] = ROUND(e.color[2]*255.0); } } WriteColor(wr, ce); fprintf(wr, " : "); Mis.WriteRadius(wr, e.radius); fprintf(wr, "\n"); } } } if (o->silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; Edge_t ae = PEdge(a); ??? aen = ae->num; ??? ea = top->edge[aen]; Place_t b = NextE(a); Edge_t be = PEdge(b); ??? ben = be->num; ??? eb = top->edge[ben]; Place_t c = PrevE(a); Edge_t cce = PEdge(c); ??? cen = cce->num; ??? ec = top->edge[cen]; with ( double cs = Row3I{0,255,255} /* color for the edges of the silhouette walls */ ){ if ((SilhouetteWalls(a))) { if ((! Present(estack, etop, aen))) { fprintf(wr, Fmt.Pad(Fmt.Int(OrgV(ea.pa)->num), eWidth) \ " " & Fmt.Pad(Fmt.Int(OrgV(Clock(ea.pa))->num), eWidth)); fprintf(wr, " : "); /* color */ WriteColor(wr, cs); fprintf(wr, " : "); Mis.WriteRadius(wr, ea.radius); fprintf(wr, "\n"); Save(estack,etop,aen); } if ((! Present(estack, etop, ben))) { fprintf(wr, Fmt.Pad(Fmt.Int(OrgV(eb.pa)->num), eWidth) \ " " & Fmt.Pad(Fmt.Int(OrgV(Clock(eb.pa))->num), eWidth)); fprintf(wr, " : "); /* color */ WriteColor(wr, cs); fprintf(wr, " : "); Mis.WriteRadius(wr, eb.radius); fprintf(wr, "\n"); Save(estack,etop,ben); } if ((! Present(estack, etop, cen))) { fprintf(wr, Fmt.Pad(Fmt.Int(OrgV(ec.pa)->num), eWidth) \ " " & Fmt.Pad(Fmt.Int(OrgV(Clock(ec.pa))->num), eWidth)); fprintf(wr, " : "); /* color */ WriteColor(wr, cs); fprintf(wr, " : "); Mis.WriteRadius(wr, ec.radius); fprintf(wr, "\n"); Save(estack,etop,cen); } } } } } fclose(wr); } } } /* END WriteWire4 */ PROCEDURE ProjectTo3D( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Coords_t *c; VAR c3: Tridimensional.Coords3D_t; ElemTableRec_t *top ) void CalcV4Matrix() /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ { /* Calculate Wd, the 4th coordinate basis vector and line-of-sight. */ Wd = r4_Sub(o->To4,o->From4); norm = r4_Norm(Wd); if (norm < Epsilon) { fprintf(stderr,"4D To Point and From Point are the same\n"); Process.Exit¦(1); } Wd = r4_Scale(1.0/norm, Wd); /* Calculate Wa, the X-axis basis vector. */ Wa = r4_cross(o->Up4,o->Over4,Wd); norm = r4_Norm(Wa); if (norm < Epsilon) { fprintf(stderr, "4D up,over and view vectors are not perpendicular\n"); Process.Exit¦(1); } Wa = r4_Scale(1.0/norm, Wa); /* Calculate Wb, the perpendicularized Up vector. */ Wb = r4_cross(o->Over4,Wd,Wa); norm = r4_Norm(Wb); if (norm < Epsilon) { fprintf(stderr,"Invalid 4D over vector\n"); Process.Exit¦(1); } Wb = r4_Scale(1.0/norm, Wb); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ Wc = r4_cross(Wd,Wa,Wb); } CalcV4Matrix; VAR Tan2Vangle4, Data4Radius, pconst, rtemp, depth: double; TempV : r4_t; Wa,Wb,Wc,Wd : r4_t; double norm; { ??? angle = o->Vangle4/2.0; ??? angler = (FLOAT(Math.Pi, double)*angle)/180.0); with( ) { Tan2Vangle4 = Math.tan(angler); } /* Find the radius of the 4D data. The radius of the 4D data is the radius of the smallest enclosing sphere, centered at the To point. Note that during the loop through the nodes, Data4Radius holds the squared radius value. */ Data4Radius = 0.0; for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); ??? Temp4 = r4_Sub(c[v->num]; with (o->To4), double dist = r4_dot(Temp4,Temp4) ){ if (dist > Data4Radius) { Data4Radius = dist; } } } Data4Radius = sqrt(Data4Radius); fprintf(stderr,"Data4Radius: "& Fmt.Pad(Fmt.LongReal(Data4Radius, Fmt.Style.Fix, prec = 4),8)&"\n"); CalcV4Matrix(); if (0 == strcmp(o->projectionName, "Parallel"))) { rtemp = 1.0 / Data4Radius; } else { pconst = 1.0 / Tan2Vangle4; } for (i = 0; i < top->node.ne; i++) { /* Transform the nodes from 4d World coordinates to 4D eye coordinates. */ Node_t v = OrgV(top->node.e[i]); { TempV = r4_Sub(c[v->num],o->From4); depth = r4_dot(TempV,Wd); if (0 == strcmp(o->projectionName, "Perspective"))) { rtemp = pconst / depth; } c3[v->num][0] = rtemp * r4_dot(TempV, Wa); c3[v->num][1] = rtemp * r4_dot(TempV, Wb); c3[v->num][2] = rtemp * r4_dot(TempV, Wc); } } } /* END ProjectTo3D */ PROCEDURE Save( Stack: REF uint_vec_t; uint *top,element; ) /* Saves the "element" on the stack "Stack". */ { Stack.El[top] = element; top++; } /* END Save */ bool_t Present( *Stack: REF uint_vec_t; uint top,element; ) /* Return TRUE if "element" its on the stack, FALSE c.c. */ nstack1: uint = top; { while (nstack1 > 0){ nstack1 = nstack1 - 1; if (Stack.El[nstack1] == element){ return TRUE; } } return FALSE; } Present; Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileSt } if ((argparser_keyword_present(pp, "-normalize"))) { /* Desired radius of model in R^4 */ o->normalize = pp.getNextLongReal(1.0d-10,1.0d+10); } else { o->normalize = 0.0 /* No normalization */ }; if ((argparser_keyword_present(pp, "-DepthCueLevels"))) { o->DepthCueLevels = argparser_get_next_int(pp, 1, 255); } else { o->DepthCueLevels = 16; } argparser_get_keyword(pp, "-projection"); o->projectionName = argparser_get_next(pp); if ((! 0 == strcmp(o->projectionName, "Parallel") OR Text.Equal(o->projectionName, "Perspective")) )){ argparser_error(pp, "Bad projection \"" & argparser_get_next(pp) & "\"\n") } if ((argparser_keyword_present(pp, "-From4"))) { for (j = 0; j < 4; j++) { o->From4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From4 = (r4_t){0.0,0.0,0.0,-5.0}; } if ((argparser_keyword_present(pp, "-To4"))) { for (j = 0; j < 4; j++) { o->To4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To4 = (r4_t){0.0,0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up4"))) { for (j = 0; j < 4; j++) { o->Up4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up4 = (r4_t){0.0,1.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Over4"))) { for (j = 0; j < 4; j++) { o->Over4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Over4 = (r4_t){0.0,0.0,1.0,0.0}; } if ((argparser_keyword_present(pp, "-Vangle4"))) { o->Vangle4 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle4 = 45.0; } if ((argparser_keyword_present(pp, "-From3"))) { for (j = 0; j < 3; j++) { o->From3[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From3 = (r3_t){2.0,1.5,3.0}; } if ((argparser_keyword_present(pp, "-To3"))) { for (j = 0; j < 3; j++) { o->To3[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To3 = (r3_t){0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up3"))) { for (j = 0; j < 3; j++) { o->Up3[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up3 = (r3_t){0.0,1.0,0.0}; } if ((argparser_keyword_present(pp, "-Vangle3"))) { o->Vangle3 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle3 = 45.0; } o->all = argparser_keyword_present(pp, "-all"); o->silhouette = argparser_keyword_present(pp, "-silhouette"); o->colored = argparser_keyword_present(pp, "-colored"); if ((argparser_keyword_present(pp, "-ordernet"))) { o->ordernet = argparser_get_next_int(pp, 1, 5); } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TriangToWire4 \\\n" \ " -inFileTp \\\n" \ " -inFileSt \\\n" \ " [ -outFile ] \\\n" \ " -projection [ Perspective | Parallel ] \\\n" \ " [-normalize ] \\\n" \ " [ -From4 ]\\ \n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ] \\\n" \ " [ -Vangle4 ] \\\n" \ " [ -From3 ] \\\n" \ " [ -To3 ] \\\n" \ " [ -Up3 ] \\\n" \ " [ -Vangle3 ] \\\n" \ " [ -DepthCueLevels ] \\\n" \ " [ -silhouette ]\n"); END¦ } } return o; } /* END GetOptions */ /* end TriangToWire4 */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/TriangToX3D.c #define PROG_NAME "TriangToX3D" #define PROG_DESC "???" #define PROG_VERS "1.0" #define TriangToX3D_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program contain procedures to write "3D topologies" (non exclusively triangulations) in X3D format (".poly"), an interactive wireframe viewer for X11. */ // #INCLUDE #include // #INCLUDE #include // #INCLUDE #include #include // // #INCLUDE // #INCLUDE #include /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ TYPE double FourNodes_t = RECORD u, v, w, x: uint; } double Color = frgb_t; typedef struct Options_t { char *inFileTp; inFileSt3 : char *; char *outFile; bool_t silhouette; /* TRUE draws the silhouette walls */ bool_t all; /* TRUE draws even non-existing triangles */ bool_t colored; /* coloring the original walls with a defined palete */ uint ordernet; /* Order on the net for original walls of the map. */ } double double = double; VAR Color palette[5+1]; /* the palette colors for the original walls. */ fac : REF ARRAY OF Color; /* the wall colors to use */ bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { assert(d!=0.0); if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? rc3 = Tridimensional.ReadState3D(o->inFileSt3); ??? top = tc.top; ??? c3 = rc3^; { WriteX3DFile(o->outFile, top, c3, o) return 0; } void WriteX3DFile(char *name, ElemTableRec_t *top, *c3: Tridimensional.Coords3D_t; Options_t op; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(name & ".poly"); { fprintf(wr, "# Created by TriangToX3D: " & name & ".poly\n"); WriteX3D(wr, top, c3, op); fclose(wr) } } /* END WriteX3DFile */ void WriteX3D(FILE *wr, *ElemTableRec_t *top; *c3: Tridimensional.Coords3D_t; Options_t op; ) double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x compute us its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; void WriteX3DCoord(double x) { fprintf(wr, Fmt.LongReal(x*1000.0, prec = 5)) } WriteX3DCoord; void WriteX3DColor(*cr: frgb_t) { fprintf(wr, Fmt.Int(ROUND(255.0*cr[0]))); fprintf(wr, " "); fprintf(wr, Fmt.Int(ROUND(255.0*cr[1]))); fprintf(wr, " "); fprintf(wr, Fmt.Int(ROUND(255.0*cr[2]))); } WriteX3DColor; void WriteX3DPoint(r3_t *p) { WriteX3DCoord(p[0]); fprintf(wr, " "); WriteX3DCoord(p[1]); fprintf(wr, " "); WriteX3DCoord(p[2]); } WriteX3DPoint; void WriteX3DWall( uint *n; *f: Triangulation.Wall; ) /* This procedure writes a n-gon wall */ REF uint_vec_t sc ; frgb_t color; { sc = NEW(REF uint_vec_t ,n); color = f.color; fprintf(wr, "# wall " & Fmt.Int(f->num) & "\n"); fprintf(wr, " "); WriteX3DColor(color); fprintf(wr, "# color \n\n"); ??? a = f.pa; { for (i = 0; i < n; i++) { sc[i] = OrgV(a)->num; fprintf(wr, " "); WriteX3DPoint(c3[sc[i]]); fprintf(wr, "\n"); a = NextE(a); }; } fprintf(wr,"\n"); fflush(wr); } WriteX3DWall; void WriteGhostTriang(u,v,w : r3_t; frgb_t color) /* This procedure writes a triangular ghost wall */ { fprintf(wr, "# ghost wall\n"); fprintf(wr, " "); WriteX3DColor(color); fprintf(wr, "# color \n\n"); fprintf(wr, " "); WriteX3DPoint(u); fprintf(wr, "\n"); fprintf(wr, " "); WriteX3DPoint(v); fprintf(wr, "\n"); fprintf(wr, " "); WriteX3DPoint(w); fprintf(wr, "\n\n"); fflush(wr); } WriteGhostTriang; void WriteInternalTriangle(f: Wall; bool_t colored; ordernet: uint) /* Writes the POV representation of an internal net for the "a.wall" (which is assumed to be a triangle). */ { ??? a = f.pa; Place_t b = NextE(a); Place_t c = NextE(b); Node_t un = OrgV(a)->num; Node_t vn = OrgV(b)->num; Node_t wn = OrgV(c)->num; ??? d0x = (c3[vn][0] - c3[un][0])/FLOAT(ordernet, double)); with( double d0y = (c3[vn][1] - c3[un][1])/FLOAT(ordernet, double); double d0z = (c3[vn][2] - c3[un][2])/FLOAT(ordernet, double); double d1x = (c3[wn][0] - c3[vn][0])/FLOAT(ordernet, double); double d1y = (c3[wn][1] - c3[vn][1])/FLOAT(ordernet, double); double d1z = (c3[wn][2] - c3[vn][2])/FLOAT(ordernet, double); double d2x = (c3[un][0] - c3[wn][0])/FLOAT(ordernet, double); double d2y = (c3[un][1] - c3[wn][1])/FLOAT(ordernet, double); double d2z = (c3[un][2] - c3[wn][2])/FLOAT(ordernet, double); fc == f.color ){ if (ordernet == 1) { /* nothing */ } else if (ordernet == 2){ for (j = 1; j < ordernet; j++) { ??? n0x = c3[vn][0] - FLOAT(j, double) * d0x); with( double n0y = c3[vn][1] - FLOAT(j, double) * d0y; double n0z = c3[vn][2] - FLOAT(j, double) * d0z; double n1x = c3[wn][0] - FLOAT(j, double) * d1x; double n1y = c3[wn][1] - FLOAT(j, double) * d1y; double n1z = c3[wn][2] - FLOAT(j, double) * d1z; double n2x = c3[un][0] - FLOAT(j, double) * d2x; double n2y = c3[un][1] - FLOAT(j, double) * d2y; double n2z = c3[un][2] - FLOAT(j, double) * d2z; n0 == (r3_t){n0x,n0y,n0z}, n1 == (r3_t){n1x,n1y,n1z}, n2 == (r3_t){n2x,n2y,n2z} ){ if (! colored) { WriteGhostTriang(n0,n1,n2,fc); } else { WriteGhostTriang(n0,n1,n2,fc); } } } } else if (ordernet == 3){ for (j = 1; j < 2; j++) { ??? n00x = c3[vn][0] - FLOAT(j, double) * d0x); with( double n00y = c3[vn][1] - FLOAT(j, double) * d0y; double n00z = c3[vn][2] - FLOAT(j, double) * d0z; n00 == (r3_t){n00x,n00y,n00z}, double n01x = c3[vn][0] - FLOAT(j+1, double) * d0x; double n01y = c3[vn][1] - FLOAT(j+1, double) * d0y; double n01z = c3[vn][2] - FLOAT(j+1, double) * d0z; n01 == (r3_t){n01x,n01y,n01z}, double n10x = c3[wn][0] - FLOAT(j, double) * d1x; double n10y = c3[wn][1] - FLOAT(j, double) * d1y; double n10z = c3[wn][2] - FLOAT(j, double) * d1z; n10 == (r3_t){n10x,n10y,n10z}, double n11x = c3[wn][0] - FLOAT(j+1, double) * d1x; double n11y = c3[wn][1] - FLOAT(j+1, double) * d1y; double n11z = c3[wn][2] - FLOAT(j+1, double) * d1z; n11 == (r3_t){n11x,n11y,n11z}, double n20x = c3[un][0] - FLOAT(j, double) * d2x; double n20y = c3[un][1] - FLOAT(j, double) * d2y; double n20z = c3[un][2] - FLOAT(j, double) * d2z; n20 == (r3_t){n20x,n20y,n20z}, double n21x = c3[un][0] - FLOAT(j+1, double) * d2x; double n21y = c3[un][1] - FLOAT(j+1, double) * d2y; double n21z = c3[un][2] - FLOAT(j+1, double) * d2z; n21 == (r3_t){n21x,n21y,n21z}, double i = Scale(1.0/FLOAT(6,double),Add(Add(Add(Add(Add(n00,n01),n10),n11),n20),n21)) ){ if (! colored) { WriteGhostTriang(n00,i,n11,fc); WriteGhostTriang(i,n21,n10,fc); WriteGhostTriang(n01,n20,i,fc); } else { WriteGhostTriang(n00,i,n11,fc); WriteGhostTriang(i,n21,n10,fc); WriteGhostTriang(n01,n20,i,fc); } } } } else { /* nothing */ } } } WriteInternalTriangle; { if (op.silhouette){ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; ??? a = f.pa; ??? der = Octf.DegreeOfEdge(a); { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WriteX3DWall(der,f); } } } } if (op.colored) { /* computing the original number walls */ uint max = 0; { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists) { max = MAX(max,f->root); } } }; fprintf(stderr,"The original number walls is " & Fmt.Int(max+1) & "\n"); fac = NEW(REF ARRAY OF Color,max+1); /* defining the palette colors with brightness aprox. 0.7 */ palette[0] = Color{1.00,0.50,1.00}; palette[1] = Color{0.00,1.00,1.00}; palette[2] = Color{0.80,0.80,0.00}; palette[3] = Color{1.00,0.60,0.60}; palette[4] = Color{0.25,1.00,0.25}; palette[5] = Color{0.70,0.70,1.00}; /* attribution of differents colors for each original wall */ for (j = 0; j <= (max); j++) { fac[j] = palette[j % 6]; } } } /* drawing the interior of the original walls as a net with the appropriate colors */ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if ((f->exists) || (op.all)) { ??? froot = f->root, der == Octf.DegreeOfEdge(f.pa); { if (op.colored){ f.color = fac[froot]; } WriteX3DWall(der,top->wall[i]); WriteInternalTriangle(top->wall[i],op.colored,op.ordernet); } } } } } /* END WriteX3D */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { ¦TRY argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt3"); o->inFileSt3 = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } o->all = argparser_keyword_present(pp, "-all"); o->silhouette = argparser_keyword_present(pp, "-silhouette"); o->colored = argparser_keyword_present(pp, "-colored"); if ((argparser_keyword_present(pp, "-ordernet"))) { o->ordernet = argparser_get_next_int(pp, 1, 5); } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: TriangToX3D \\\n" \ " -inFileTp -inFileSt3 \\\n" \ " [-outFile ] [-all] [-silhouette] [-colored]\n"); END¦ } } return o; } /* END GetOptions */ /* end TriangToX3D */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/UnglueCell.c #define PROG_NAME "UnglueCell" #define PROG_DESC "???" #define PROG_VERS "1.0" #define UnglueCell_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " // #INCLUDE #include #include // #INCLUDE // #INCLUDE // MakeCellTopology, Place_t; // #INCLUDE // NextE, Srot; TYPE typedef struct Options_t { char *inFile; uint cellnum; char *outFile; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Place_t *b; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; ??? a = Srot(top->cell[o->cellnum]); ??? top = MakeCellTopology(a); { /* ungluing the cell top->cell[i] */ for (j = 0; j < top.wall.ne; j++) { ??? fer = top.fRef[j] DO b = fer; do { Triangulation.SetOrg(Srot(b); with (NULL); b = NextE(b) } while (!( b == fer)); } } /* building the new topology */ ??? top = MakeElemTable(top->node[top->node.ne-1]; with (1), double c = GenCoords(top)^; double name = o->outFile ){ WriteTopology(name, top, "Created by MakeGem: " & name & ".top on " \ Today()); WriteMaterials(name, top, "Created by MakeGem: " & name& ".ma on " \ Today()); WriteState(name, top, c, "Created by MakeGem: " & name & ".st on " \ Today() &"\nRandom Geometry"); } return 0; } Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-cellnum"); o->cellnum = argparser_get_next_int(pp, ); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Teste" \ " -inFile " \ "\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } UnglueCell. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/UngluingCell.c #define PROG_NAME "UngluingCell" #define PROG_DESC "???" #define PROG_VERS "1.0" #define UngluingCell_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Given a map or any refinement of its, this program unglued any specified cell of the map. */ // #INCLUDE #include #include // #INCLUDE // #INCLUDE // // #INCLUDE // MakeCellTopology, Place_t, Pneg, Ppos, OrgV; // #INCLUDE // NextE, Srot; TYPE typedef struct Options_t { char *inFile; uint cellnum; char *outFile; bool_t polyroot; } Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Place_t *b; tc : Triangulation.TopCom_t; ElemTableRec_t top; old@{edge->?}: REF ARRAY OF INTEGER; oldwall: REF ARRAY OF INTEGER; oldcoor: REF ARRAY OF INTEGER; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? rc = Triangulation.ReadState(o->inFile); ??? c = rc^; { if (o->polyroot ){ tc = Triangulation.ReadToMa(o->inFile, TRUE); } else { tc = Triangulation.ReadToMa(o->inFile, FALSE); } fprintf(stderr,"Ungluing the cell number "&Fmt.Int(o->cellnum) & "\n"); top = tc.top; old@{edge->?} = NEW(REF ARRAY OF INTEGER, top->wall.nelE); oldwall = NEW(REF ARRAY OF INTEGER, top->wall.nelE); oldcoor = NEW(REF ARRAY OF INTEGER, top->wall.nelE); for (i = 0; i < top->wall.nelE; i++) { old@{edge->?}[i] = PWedge(top->wedge[i]).edge->num; oldwall[i] = PWedge(top->wedge[i]).wall->num; oldcoor[i] = OrgV(top->wedge[i])->num } for (i = 0; i < top->wall.nelE; i++) { ??? a = NARROW(PWedge(top->wedge[i]); with ( TriangulationWedge_t) ){ a.old = i; } } if (o->polyroot) { for (i = 0; i < top->cell.ne; i++) { if (top->cell[i]->root == o->cellnum) { ??? a = Srot(top.cell[i]); ??? top = MakeCellTopology(a); { /* ungluing the cell top->cell[i] */ for (j = 0; j < top.wall.ne; j++) { ??? fer = top.fRef[j]; { b = fer; do { Triangulation.SetOrg(Srot(b), NULL); b = NextE(b) } while (!( b == fer)); } } } } } } else { ??? a = Srot(top->cell[o->cellnum]); ??? top = MakeCellTopology(a); { /* ungluing the cell top->cell[i] */ for (j = 0; j < top.wall.ne; j++) { ??? fer = top.fRef[j]; { b = fer; do { Triangulation.SetOrg(Srot(b), NULL); b = NextE(b) } while (!( b == fer)); } } } } for (i = 0; i < top->wall.nelE; i++) { ??? a = top->wedge[i]; ??? n = Pneg(a); ??? p = Ppos(a); { if ((n == NULL) && (p == NULL)) { Place_t *b; { b = a; do { Octf.DeleteWedge(b); b = NextE(b); } while (b != a); } } } } /* building the new topology */ INTEGER Number() { for (k = 0; k < top->wall.nelE; k++) { ??? l = top->wedge[k]; { if (((Ppos(l)#NULL)) && ((Pneg(l)#NULL))){ return k; }; } } return -1; } Number; { ??? l = Number(); ??? top = MakeElemTable(top->wedge[l]); ??? cc = GenCoords(top)^; with ( double name = o->outFile DO /* Update the new topology */ for (i = 0; i < top.edge.ne; i++) { ??? a = top.edge[i]; { Octf.SetRingEdgeInfo(a.pa, a); } } for (i = 0; i < top.wall.ne; i++) { ??? a = top.wall[i]; { Octf.SetRingWallInfo(a.pa, a); } } for (i = 0; i < top.wedge.ne; i++) { ??? fe = NARROW(PWedge(top.wedge[i]); with ( TriangulationWedge_t), double o = fe.old; double ne = PWedge(top.wedge[i]).edge->num; double nf = PWedge(top.wedge[i]).wall->num; double nv = OrgV(top.wedge[i])->num; double oe = old@{edge->?}[o]; double of = oldwall[o]; double ov = oldcoor[o] ){ /* @{edge->?} */ top.edge[ne]->exists = top->edge[oe]->exists; top.edge[ne].color = top->edge[oe].color; top.edge[ne].transp = top->edge[oe].transp; top.edge[ne].radius = top->edge[oe].radius; top.edge[ne]->root = top->edge[oe]->root; /* wall */ top.wall[nf]->exists = top->wall[of]->exists; top.wall[nf].color = top->wall[of].color; top.wall[nf].transp = top->wall[of].transp; top.wall[nf]->root = top->wall[of]->root; /* node */ cc.e[nv] = c[ov]; } } WriteTopology(name, top, "Created by MakeGem: " & name & ".tp on " \ Today()); WriteMaterials(name, top, "Created by MakeGem: " & name& ".ma on " \ Today(),FALSE); WriteState(name, top, cc, "Created by MakeGem: " & name & ".st on " \ Today() &"\nRandom Geometry"); } } return 0; } Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-cellnum"); o->cellnum = argparser_get_next_int(pp, ); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->polyroot = argparser_keyword_present(pp, "-polyroot"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: UngluingCell -inFile \\\n" \ " -outFile -cellnum [-polyroot]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } UngluingCell. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Unshellable.c #define PROG_NAME "Unshellable" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Unshellable_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " // #INCLUDE #include // #INCLUDE // #INCLUDE #include #include // // #INCLUDE // #INCLUDE TYPE typedef struct Options_t { uint gridOrder; } TYPE double @PLACES = ARRAY[0..3] OF Place_t; Place_t MakeBigRawCube(uint order) /* Build one tridimensional array of cubic cellulas with fixed geometry.*/ VAR cd : REF ARRAY OF ARRAY OF ARRAY OF @PLACES; { cd = NEW(REF ARRAY OF ARRAY OF ARRAY OF @PLACES, 5, order, order); for (i = 0; i < 5; i++) { ??? cc = Squared.Make2DCubeArray(order); { for (j = 0; j < order; j++) { for (k = 0; k < order; k++) { for (l = 0; l < 2; l++) { cd[i,j,k,l] = cc.e[j,k,l]; } } } } } /* gluing */ for (i = 0; i < 4; i++) { for (k = 0; k < order; k++) { for (j = 0; j < order; j++) { GlueCube(cd[i,k,j,1],Clock(cd[i+1,k,j,0])); } } } /* Fix the coordinates */ ??? top = MakeElemTable(cd[0; with (0,0,0],1), double r = NEW(REF Coords_t, top->node.ne); double c = r^; double name = "Bigcube-" & Fmt.Int(order); double zero = 0.0; double one = 1.0; double cmt = " " ){ void SetCorner(e: Place_t; uint i) { ??? ii = FLOAT(i, double)); with( double cv = (r4_t){ii,zero,zero,zero} ){ c[OrgV(e)->num] = cv; } } SetCorner; void SetCorner1(e: Place_t; o: r4_t) { c[OrgV(e)->num] = (r4_t){o[0], o[1]+one, o[2], o[3]}; } SetCorner1; void SetCorner2(e: Place_t; o: r4_t) { c[OrgV(e)->num] = (r4_t){o[0], o[1], o[2]+one, o[3]}; } SetCorner2; void SetCorner3(e: Place_t; o: r4_t) { c[OrgV(e)->num] = (r4_t){o[0], o[1]-one, o[2], o[3]}; } SetCorner3; Place_t *p; { for (i = 0; i < 5; i++) { SetCorner(Clock(NextE(cd[i,0,0,0])),i); for (j = 0; j < order; j++) { p = Clock(NextE(cd[i,j,0,0])); for (k = 0; k < order; k++) { SetCorner1(NextE(p),c[OrgV(p)->num]); SetCorner2(NextE(NextE(p)),c[OrgV(NextE(p))->num]); SetCorner3(NextE(NextE(NextE(p))),c[OrgV(NextE(NextE(p)))->num]); p = NextE(PrevF(PrevF(cd[i,j,k,0]))); } } } /* finally */ SetCorner(PrevE(cd[4,0,0,1]),order); for (j = 0; j < order; j++) { p = PrevE(cd[4,j,0,1]); for (k = 0; k < order; k++) { SetCorner1(NextE(p),c[OrgV(p)->num]); SetCorner2(NextE(NextE(p)),c[OrgV(NextE(p))->num]); SetCorner3(NextE(NextE(NextE(p))),c[OrgV(NextE(NextE(p)))->num]); p = Clock(PrevE(NextF(cd[4,j,k,1]))); } } WriteTopology(name,top); MakeElemTableTable(name, top, cmt); WriteState(name, top, c, cmt); WriteMaterials(name, top, cmt); return cd[0,0,0,0]; } } } /* END MakeBigRawCube */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-gridOrder"); o->gridOrder = argparser_get_next_int(pp, 1,10); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: MakeRawCube -gridOrder \n"); END¦ } } return o; } /* END GetOptions */ PROCEDURE Main() Place_t *a; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ { a = MakeBigRawCube(o->gridOrder); } } /* END Main */ { Main(); } Unshellable. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Visibility.c #define PROG_NAME "Visibility" #define PROG_DESC "???" #define PROG_VERS "1.0" #define Visibility_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program implements the "visibility" of a 3D projection. Given a 4D (optimized) configuration, and the viewing parameters of the 4D observer (From4, Up4, etc), writes a POVRAY ".inc" file con- taining the 3D projection of the 4D configuration as "seen" from that viewpoint. The projection will use distinct textures (and optionally omit) the "front" and "back" elements, as well as, the silhouette walls. The back/front test assumes that the tetrahedra constitute the shell of a convex polytope and that the observer is outside that shell. The test consists in computing the orientation of each tetrahedron of the 3D-projected triangulation with reference to the observer and with reference to the "barycenter" of the configuration. Depending the position of the 4D observer we obtain different orientations. Use the option "both" to show both front and back elements. Use the option "-fade" to paint the back elements with faded colors. Use "back" or "front" to show only those elements. If "From4" is not given as an option, the program reads zero or more lines from stdin, each containing an index "i", a value of "From4", one output option ("front"/"back"/"both") and writes one ".inc" file for each such line. */ // #INCLUDE #include #include #include #include // #INCLUDE #include #include //#include // // #INCLUDE #include // stderr, stdin; // #INCLUDE // NextE, PrevE, Tors, Clock, NextF; // #INCLUDE // WritePOVSphere, WritePOVCylinder, WritePOVTriangle; #include CONST double Epsilon = 0.0000000001; TYPE Options_t == RECORD char *inFileTp; /* Input file prefix (topology, tabel, materials).*/ char *inFileSt; /* Input file prefix (4D geometry). */ char *outFile; /* Output file prefix (POVray include files). */ bool_t wire; /* Don't draw walls. */ bool_t detail; /* Debugging. */ bool_t silhouette; /* Draw the silhouette walls. */ bool_t perspective; /* TRUE means perspective projection. */ bool_t autoProject; /* The program choses the viewpoint. */ bool_t filter; /* TRUE uses filtered colors, FALSE transmit colors.*/ bool_t fade; /* Make the back elements fainter. */ bool_t normalize; /* Norm. al nodes onto the S^3 with that radius. */ bool_t multiple; /* T reads multiple "From4"s and "side"s from stdin.*/ From4: r4_t; /* Viewpoint in 4D. */ To4: r4_t; /* 4D viewing parameters as expected by the */ Up4: r4_t; /* "Wire4"- Interactive 4D Wireframe Display */ Over4: r4_t; /* Program. */ Vangle4: double; /* */ Side select; /* Which elements to show in the output. */ char *selectTxt; /* Ditto, in text format. */ bool_t colored; /* coloring the original walls with a palette*/ } /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ FourNodes_t == RECORD u, v, w, x: uint; } Side == {Back, Front, Both}; Color == frgb_t; PACK == RECORD bool_t belong; num: INTEGER; } <* FATAL Rd.Failure, Wr.Failure, Thread.Alerted, FloatMode.Trap, Lex.Error); PROCEDURE @{Edge->?}BelongsToOriginalWall(Place_t @p, ElemTableRec_t *top): PACK == /* Returns TRUE if the edge component of "a" belongs to a wall of the original map also accomplish the number of the original wall. */ VAR Place_t b = a; PACK pack; { if ((top->edge[PEdge(a)->num]->root!=-1)){ pack.belong = FALSE; pack->num = -1; return pack; } /* Check if any wall incident to "a" belongs to a wall of the map. */ do { if ((top->wall[PWall(b)->num]->root!=-1)) { pack.belong = TRUE; pack->num = PWall(b)->num; return pack; } b = NextF(b) } while (b != a); pack.belong = FALSE; pack->num = -1; return pack; } /* END @{Edge->?}BelongsToOriginalWall */ bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { /*assert(d!=0.0);*/ if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ uint i; { ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? top = tc.top; ??? rc4 = Triangulation.ReadState(o->inFileSt); ??? rc3 = NEW(REF Tridimensional.Coords3D_t; with (top->node.ne), c4 == rc4^, c3 == rc3^ ){ if (o->normalize) { fprintf(stderr, "projecting nodes onto the unit S^3\n"); Triangulation.NormalizeNodeDistances(top, c4, o->normalize); } if (o->autoProject) { fprintf(stderr, "selecting camera parameters\n"); SelectProjection(o, c4, top); } fprintf(stderr, "projecting and converting to POV-Ray\n"); if (o->multiple) { while (1) { Lex.Skip(stdin, Lex.Blanks); if ((Rd.EOF(stdin))){ EXIT; } i = fget_int32(stdin); o->From4[0] = Lex.LongReal(stdin); o->From4[1] = Lex.LongReal(stdin); o->From4[2] = Lex.LongReal(stdin); o->From4[3] = Lex.LongReal(stdin); Lex.Skip(stdin, Lex.Blanks); o->selectTxt = Lex.Scan(stdin); if (0 == strcmp(o->selectTxt, "back"))) { o->select = Side.Back; } else if (0 == strcmp(o->selectTxt, "front"))){ o->select = Side.Front; } else if (0 == strcmp(o->selectTxt, "both"))){ o->select = Side.Both; } else { fprintf(stderr, "Bad shape \"" & o->selectTxt & "\"\n"); Process.Exit¦(1) } ProjectTo3D(o, c4, c3, top); ??? itx = Fmt.Pad(Fmt.Int(i), 4, '0'); { WritePOV(o->outFile & "-" & o->selectTxt & "-" & itx, top, c3, c4, o) } } } else { ProjectTo3D(o, c4, c3, top); WritePOV(o->outFile & "-" & o->selectTxt, top, c3, c4, o) } return 0; } void WritePOV(char *name, ElemTableRec_t *top, * c3: Tridimensional.Coords3D_t; * c4: Coords_t; Options_t * o; ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(name & ".inc"); { fprintf(wr, "// Include File: <" & name & ".inc>\n"); DoWritePOV(wr, top, c3, c4, o); fclose(wr) } } /* END WritePOV */ PROCEDURE DoWritePOV ( FILE *wr, *ElemTableRec_t *top; * c3: Tridimensional.Coords3D_t; Coords_t * c; Options_t * o; ) == VAR vseen = NEW(REF ARRAY OF bool_t, top->node.ne); /* stack for nodes */ eseen = NEW(REF ARRAY OF bool_t, top->NE); /* stack for edges */ fseen = NEW(REF ARRAY OF bool_t, top->wall.ne); /* stack for walls */ quad : REF ARRAY OF FourNodes_t; bool_t IsFront(q: FourNodes_t) { ??? u = r4_Sub(c[q.u]; with (cb), v == r4_Sub(c[q.v],cb), w == r4_Sub(c[q.w],cb), x == r4_Sub(c[q.x],cb), double d1 = r4_det(u,v,w,x); double u_ = r4_Sub(c[q.u],o->From4); double v_ = r4_Sub(c[q.v],o->From4); double w_ = r4_Sub(c[q.w],o->From4); double x_ = r4_Sub(c[q.x],o->From4); double d2 = r4_det(u_,v_,w_,x_) DO return (Sign(d1)) && (NOT Sign(d2))) || (( NOT Sign(d1)) && (Sign(d2)); } } IsFront; double FindOrientR3(q: FourNodes_t) { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOrientR3; bool_t IsSilhouette(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOrientR3(t1); double d2 = FindOrientR3(t2) DO return (Sign(d1)) && (Sign(d2))) || ((NOT Sign(d1)) && (NOT Sign(d2)); } } IsSilhouette; void WritePOVNode(s: Triangulation.Node; fade: REAL; fbTag: char *) char **dimTag; { ??? ff = ((double)fade); ??? ts = s.transp; ??? ts = (ts[0] + ts[1] + ts[2]) / 3.0 * fade; ??? tc = R3.Mix(ff; with (s.color, 1.0 - ff, (frgb_t){0.5,0.5,0.5}) ){ if ((s->exists) && (NOT vseen[s->num])) { if (0 == strcmp(s.label, "VV"))){ dimTag = "node" } else { dimTag = "@{edge->?}" } WritePOVSphere(wr, c3[s->num], s.radius, tc, ts, TRUE, dimTag, fbTag); vseen[s->num] = TRUE } } } WritePOVNode; void WritePOVWall(t: Triangulation.Wall; fade: REAL; fbTag: char *) { ??? ff = ((double)fade); ??? ts = t.transp; ??? ts = (ts[0] + ts[1] + ts[2]) / 3.0 * fade; ??? tc = R3.Mix(ff; with (t.color, 1.0 - ff, (frgb_t){0.5,0.5,0.5}), double a = t.pa; double b = NextE(a); double c = NextE(b); double v0 = OrgV(a)->num; double v1 = OrgV(b)->num; double v2 = OrgV(c)->num ){ if ((t->exists) && (NOT fseen[t->num])) { WritePOVTriangle(wr, c3[v0], c3[v1], c3[v2], tc, ts, TRUE, "wall", fbTag); fseen[t->num] = TRUE } } } WritePOVWall; void WritePOVSilhouetteWall(t: Triangulation.Wall) { ??? ts = 0.99; with ( double tc = (frgb_t){1.00, 0.99, 0.99}; double a = t.pa; double b = NextE(a); double c = NextE(b); double v0 = OrgV(a)->num; double v1 = OrgV(b)->num; double v2 = OrgV(c)->num ){ WritePOVTriangle(wr, c3[v0], c3[v1], c3[v2], tc, ts, o->filter, "wall", "silhouette"); } } WritePOVSilhouetteWall; PROCEDURE WritePOV@{Edge->?}(a: Triangulation.edge; fade: REAL; Color color; fbTag: char *) == { ??? ff = ((double)fade); ??? ts = a.transp; ??? ts = (ts[0] + ts[1] + ts[2]) / 3.0 * fade; ??? tc = R3.Mix(ff; with (color, 1.0 - ff, (frgb_t){0.5,0.5,0.5}), double v0 = OrgV(a.pa)->num; double v1 = OrgV(Clock(a.pa))->num ){ if ((a->exists) && (NOT eseen[a->num])) { WritePOVCylinder(wr, c3[v0], c3[v1], a.radius, tc, ts, o->filter, "@{edge->?}", fbTag); eseen[a->num] = TRUE }; } } WritePOV@{Edge->?}; PROCEDURE Write@{Edge->?}Colored(e: Triangulation.edge) == /* draws one colored @{edge->?}. */ { ??? a = e.pa; { if ((e->exists) && (@{Edge->?}BelongsToOriginalWall(a,top).belong)) { /* an @{edge->?} on the net belonging to some original wall */ ??? facc = @{Edge->?}BelongsToOriginalWall(a; with (top)->num, double froot = top->wall[facc]->root ){ WritePOV@{Edge->?}(e, fadeFactor, fac[froot], "Net"); } } else if ((e->exists) && (NOT @{Edge->?}BelongsToOriginalWall(a,top).belong)){ /* an @{edge->?} of the map */ WritePOV@{Edge->?}(e, fadeFactor, e.color, "Map"); } } } Write@{Edge->?}Colored; VAR bool_t isFront; REAL fadeFactor; char *textureTag; cb: r4_t; Color palette[5+1]; max : uint = 0; fac : REF ARRAY OF Color; /* the wall colors to use */ { cb = Barycenter(top,c,TRUE); quad = NEW(REF ARRAY OF FourNodes_t, top->cell.ne); for(i = 0; i < vseen.ne; i++){ vseen[i] = FALSE; } for(i = 0; i < fseen.ne; i++){ fseen[i] = FALSE; } for(i = 0; i < eseen.ne; i++){ eseen[i] = FALSE; } if (o->colored) { /* computing the original number walls */ for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists) { max = MAX(max,f->root); } } } fprintf(stderr, "The original number walls is " \ Fmt.Int(max+1)&"\n"); fac = NEW(REF ARRAY OF Color,max+1); /* defining the palette colors with brightness aprox. 0.7 */ palette[0] = Color{1.00,0.50,1.00}; palette[1] = Color{0.00,1.00,1.00}; palette[2] = Color{0.80,0.80,0.00}; palette[3] = Color{1.00,0.60,0.60}; palette[4] = Color{0.25,1.00,0.25}; palette[5] = Color{0.70,0.70,1.00}; /* attribution of differents colors for each original wall */ for (j = 0; j <= (max); j++) { fac[j] = palette[j % 6]; } for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (f->exists) { ??? froot = f->root; { f.color = fac[froot];} } } } } for (i = 0; i < top->cell.ne; i++) { ??? da = Srot(top.cell[i]); Place_t a0 = Tors(da); Place_t db = Clock(PrevE(da)); Place_t b0 = Tors(db); Place_t a1 = NextE(a0); Place_t a2 = NextE(a1); Node_t un = OrgV(a0)->num; Node_t vn = OrgV(a1)->num; Node_t wn = OrgV(a2)->num; Node_t xn = OrgV(PrevE(b0))->num; { quad[i] = FourNodes_t{un,vn,wn,xn}; isFront = IsFront(quad[i]); if (o->detail) { fprintf(stderr,"Tetrahedron " & Fmt.Int(i) & " on "); } if (((isFront) && (o->select!=Side.Back) OR (NOT isFront) && (o->select!=Side.Front))){ if (o->detail) { fprintf(stderr, "isFront == " & Fmt.Int(ORD(isFront)) & "\n"); } if ((o->fade) && (NOT isFront)) { fadeFactor = 0.5; textureTag = "back" } else { fadeFactor = 1.0; textureTag = "front" } ??? ri = Srot(top.cell[i]); Place_t a = Tors(ri); Place_t db = Clock(PrevE(ri)); Place_t b0 = Tors(db); Place_t a1 = NextE(a); Place_t a2 = NextE(a1); Node_t v0 = OrgV(a)->num; ??? v1 = OrgV(a1)->num; ??? v2 = OrgV(a2)->num; ??? v3 = OrgV(PrevE(b0))->num; ??? s0 = top->node[v0]; ??? s1 = top->node[v1]; ??? s2 = top->node[v2]; ??? s3 = top->node[v3]; with ( /* walls */ double walls = Triangulation.TetraWalls(a); double f0 = walls[0]->num; double f1 = walls[1]->num; double f2 = walls[2]->num; double f3 = walls[3]->num; double t0 = top->wall[f0]; double t1 = top->wall[f1]; double t2 = top->wall[f2]; double t3 = top->wall[f3]; /* @{edge->?}s */ double @{edge->?}s = Triangulation.TetraEdges(a); double e0 = @{edge->?}s[0]->num; double e1 = @{edge->?}s[1]->num; double e2 = @{edge->?}s[2]->num; double e3 = @{edge->?}s[3]->num; double e4 = @{edge->?}s[4]->num; double e5 = @{edge->?}s[5]->num; double a0 = top->edge[e0]; double a1 = top->edge[e1]; double a2 = top->edge[e2]; double a3 = top->edge[e3]; double a4 = top->edge[e4]; double a5 = top->edge[e5]; double dc = (frgb_t){1.00,1.000,0.500} /* DF color por @{edge->?} net */ ){ WritePOVNode(s0, fadeFactor, textureTag); WritePOVNode(s1, fadeFactor, textureTag); WritePOVNode(s2, fadeFactor, textureTag); WritePOVNode(s3, fadeFactor, textureTag); /* write walls */ if (! o->wire) { WritePOVWall(t0, fadeFactor, textureTag); WritePOVWall(t1, fadeFactor, textureTag); WritePOVWall(t2, fadeFactor, textureTag); WritePOVWall(t3, fadeFactor, textureTag); } if (! o->colored) { /* write @{edge->?}s */ if (a0->root!=-1) { WritePOV@{Edge->?}(a0, fadeFactor, a0.color, textureTag); } else { WritePOV@{Edge->?}(a0, fadeFactor, dc, "Net"); } if (a1->root!=-1) { WritePOV@{Edge->?}(a1, fadeFactor, a1.color, textureTag); } else { WritePOV@{Edge->?}(a1, fadeFactor, dc, "Net"); } if (a2->root!=-1) { WritePOV@{Edge->?}(a2, fadeFactor, a2.color, textureTag); } else { WritePOV@{Edge->?}(a2, fadeFactor, dc, "Net"); } if (a3->root!=-1) { WritePOV@{Edge->?}(a3, fadeFactor, a3.color, textureTag); } else { WritePOV@{Edge->?}(a3, fadeFactor, dc, "Net"); } if (a4->root!=-1) { WritePOV@{Edge->?}(a4, fadeFactor, a4.color, textureTag); } else { WritePOV@{Edge->?}(a4, fadeFactor, dc, "Net"); } if (a5->root!=-1) { WritePOV@{Edge->?}(a5, fadeFactor, a5.color, textureTag); } else { WritePOV@{Edge->?}(a5, fadeFactor, dc, "Net"); } } else { Write@{Edge->?}Colored(a0); Write@{Edge->?}Colored(a1); Write@{Edge->?}Colored(a2); Write@{Edge->?}Colored(a3); Write@{Edge->?}Colored(a4); Write@{Edge->?}Colored(a5); } } } else { if (o->detail) { fprintf(stderr, "front == " & Fmt.Int(ORD(isFront)) & "\n"); } } } } if (o->silhouette) { for (i = 0; i < top->wall.ne; i++) { ??? f = top->wall[i]; { if (! f->exists) { with (a == f.pa) { if ((IsSilhouette(a))) { if (o->detail) { fprintf(stderr, "Silhouette wall: " & Fmt.Int(i) & "\n"); } WritePOVSilhouetteWall(f) } } } } } } } /* END DoWritePOV */ PROCEDURE ProjectTo3D( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Coords_t *c; VAR c3: Tridimensional.Coords3D_t; ElemTableRec_t *top ) void CalcV4Matrix() /* This procedure computes the four basis vectors for the 4D viewing matrix, Wa,Wb,Wc, and Wd. Note that the Up vector transforms to Wb, the Over vector transforms to Wc, and the line of sight transforms to Wd. The Wa vector is then computed from Wb,Wc and Wd. */ { /* Calculate Wd, the 4th coordinate basis vector and line-of-sight. */ Wd = r4_Sub(o->To4,o->From4); norm = r4_Norm(Wd); if (norm < Epsilon) { fprintf(stderr,"4D To Point and From Point are the same\n"); Process.Exit¦(1); } Wd = r4_Scale(1.0/norm, Wd); /* Calculate Wa, the X-axis basis vector. */ Wa = r4_cross(o->Up4,o->Over4,Wd); norm = r4_Norm(Wa); if (norm < Epsilon) { fprintf(stderr, "4D up,over and view vectors are not perpendicular\n"); Process.Exit¦(1); } Wa = r4_Scale(1.0/norm, Wa); /* Calculate Wb, the perpendicularized Up vector. */ Wb = r4_cross(o->Over4,Wd,Wa); norm = r4_Norm(Wb); if (norm < Epsilon) { fprintf(stderr,"Invalid 4D over vector\n"); Process.Exit¦(1); } Wb = r4_Scale(1.0/norm, Wb); /* Calculate Wc, the perpendicularized Over vector. Note that the resulting vector is already normalized, since Wa, Wb and Wd are all unit vectors. */ Wc = r4_cross(Wd,Wa,Wb); } CalcV4Matrix; VAR Tan2Vangle4, Data4Radius, pconst, rtemp, depth: double; TempV : r4_t; Wa,Wb,Wc,Wd : r4_t; double norm; { ??? angle = o->Vangle4/2.0; ??? angler = (FLOAT(Math.Pi, double)*angle)/180.0); with( ) { Tan2Vangle4 = Math.tan(angler); } /* Find the radius of the 4D data. The radius of the 4D data is the radius of the smallest enclosing sphere, centered at the To point. Note that during the loop through the nodes, Data4Radius holds the squared radius value. */ Data4Radius = 0.0; for (i = 0; i < top->node.ne; i++) { Node_t v = OrgV(top->node.e[i]); ??? Temp4 = r4_Sub(c[v->num]; with (o->To4), double dist = r4_dot(Temp4,Temp4) ){ if (dist > Data4Radius) { Data4Radius = dist; } } } Data4Radius = sqrt(Data4Radius); fprintf(stderr,"Data4Radius: "& Fmt.Pad(Fmt.LongReal(Data4Radius, Fmt.Style.Fix, prec = 4),8)&"\n"); CalcV4Matrix(); if (o->perspective) { pconst = 1.0 / Tan2Vangle4; } else { rtemp = 1.0 / Data4Radius; } for (i = 0; i < top->node.ne; i++) { /* Transform the nodes from 4d World coordinates to 4D eye coordinates. */ Node_t v = OrgV(top->node.e[i]); { TempV = r4_Sub(c[v->num],o->From4); depth = r4_dot(TempV,Wd); if (o->perspective) { rtemp = pconst / depth; } c3[v->num][0] = rtemp * r4_dot(TempV, Wa); c3[v->num][1] = rtemp * r4_dot(TempV, Wb); c3[v->num][2] = rtemp * r4_dot(TempV, Wc); } } } /* END ProjectTo3D */ PROCEDURE SelectProjection( Options_t *o = (Options_t *)malloc(sizeof(Options_t)); Coords_t *c, ElemTableRec_t *top) norm: r4_t = (r4_t){0.0, ..}; { for (i = 0; i < top->cell.ne; i++){ ??? f = Srot(top.cell[i]); ??? k = Triangulation.TetraNegNodes(f); ??? p = c[k[0]->num]; ??? q = c[k[1]->num]; ??? r = c[k[2]->num]; ??? s = c[k[3]->num]; ??? pq = r4_Sub(q; with ( p), double pr = r4_Sub(r, p); double ps = r4_Sub(s, p); double v = r4_cross(pq, pr, ps); double n = r4_Dir(v) ){ norm = r4_Add(norm, n) } } ??? m = r4_Norm(norm); { if (m < 1.0d-20) { norm = (r4_t){1.0, 0.0, ..} } else { norm = r4_Scale(1.0/m, norm) } } ??? bar = Barycenter(top; with (c,TRUE) ){ o->To4 = bar; o->From4 = r4_Add(o->To4, norm); SelectTwoIndepDirs(norm, o->Up4, o->Over4); o->Vangle4 = 120.0; } } /* END SelectProjection */ PROCEDURE SelectTwoIndepDirs( *u: r4_t; VAR v, w: r4_t; ) /* Selects two vectors "v", "w", independent of each other and of the given vector "u". */ m: uint = 0; { /* Find the largest coordinate of "u": */ for (i = 1; i < 4; i++){ if ((fabs(u[i]) > fabs(u[m]))){ m = i; } } for (i = 0; i < 4; i++){ v[i] = 0.0; w[i] = 0.0; } v[(m+1) % 4] = 1.0; w[(m+2) % 4] = 1.0; } /* END SelectTwoIndepDirs */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt"); o->inFileSt = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } o->fade = argparser_keyword_present(pp, "-fade"); o->wire = argparser_keyword_present(pp, "-wire"); o->detail = argparser_keyword_present(pp, "-detail"); o->filter = argparser_keyword_present(pp, "-filter"); if ((argparser_keyword_present(pp, "-silhouette"))) { o->silhouette = TRUE; } argparser_get_keyword(pp, "-projection"); ??? pname = argparser_get_next(pp); { if (0 == strcmp(pname, "parallel"))) { o->perspective = FALSE; } else if (0 == strcmp(pname, "perspective"))){ o->perspective = TRUE; } else { argparser_error(pp, "Bad projection \"" & pname & "\"\n"); } } if ((argparser_keyword_present(pp, "-normalize"))) { o->normalize = TRUE; } else { o->normalize = FALSE; }; if ((argparser_keyword_present(pp, "-autoProject"))) { /* Program chooses From4: */ o->autoProject = TRUE; o->multiple = FALSE; } else { /* User may give "From4" */ o->autoProject = FALSE; o->multiple = argparser_keyword_present(pp, "-multiple"); if (o->multiple) { /* Multiple From4"s will be read from stdin */ o->From4 = (r4_t){0.0,0.0,0.0,0.0} } else { /* User may give single From4 option, or take default */ if ((argparser_keyword_present(pp, "-From4"))) { for (j = 0; j < 4; j++) { o->From4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->From4 = (r4_t){100.0,50.0,20.0,0.0} } } } if (! o->multiple) { argparser_get_keyword(pp, "-select"); o->selectTxt = argparser_get_next(pp); if (0 == strcmp(o->selectTxt, "back"))) { o->select = Side.Back; } else if (0 == strcmp(o->selectTxt, "front"))){ o->select = Side.Front; } else if (0 == strcmp(o->selectTxt, "both"))){ o->select = Side.Both; } else { argparser_error(pp, "Bad shape \"" & o->selectTxt & "\"\n"); } }; if ((argparser_keyword_present(pp, "-To4"))) { for (j = 0; j < 4; j++) { o->To4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->To4 = (r4_t){0.0,0.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Up4"))) { for (j = 0; j < 4; j++) { o->Up4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Up4 = (r4_t){0.0,1.0,0.0,0.0}; } if ((argparser_keyword_present(pp, "-Over4"))) { for (j = 0; j < 4; j++) { o->Over4[j] = pp.getNextLongReal(-100.0, 100.0); } } else { o->Over4 = (r4_t){0.0,0.0,1.0,0.0}; } if ((argparser_keyword_present(pp, "-Vangle4"))) { o->Vangle4 = pp.getNextLongReal(1.0, 179.0); } else { o->Vangle4 = 25.0; }; if ((argparser_keyword_present(pp, "-colored"))) { o->colored = TRUE; } else { o->colored = FALSE; } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: Visibility \\\n" \ " -inFileTp \\\n" \ " -inFileSt -outFile \\\n" \ " -select [back | front | both] [-fade]\\\n" \ " [ -wire ] [ -detail ] [-filter ] \\\n" \ " [ -silhouette ] [-normalize ] \\\n" \ " -projection [ perspective | parallel ]\\\n" \ " [ [ -autoProject ] | \\\n" \ " [ -From4 ] \\\n" \ " [ -To4 ] \\\n" \ " [ -Up4 ] \\\n" \ " [ -Over4 ] \\\n" \ " ] \\\n" \ " [ -Vangle4 ] [ -colored ]\n"); END¦ } } return o; } /* END GetOptions */ nil { DoIt(); } Visibility. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Volume.c /* Programa para testar o volume de um tetraedro no R4 Mediante o uso do produto vetorial e mediante as coordenadas de seus nodes que o definem */ #ifndef _H #define _H #include #include #include double CalVol(*p1,p2,p3,p4: r4_t) d1,d2,d3,d4,vol : double; { with ( double l1 = (r4_t){p1[0],p1[1],p1[2],1.0}; double l2 = (r4_t){p2[0],p2[1],p2[2],1.0}; double l3 = (r4_t){p3[0],p3[1],p3[2],1.0}; double l4 = (r4_t){p4[0],p4[1],p4[2],1.0}; double l5 = (r4_t){p1[0],p1[1],p1[3],1.0}; double l6 = (r4_t){p2[0],p2[1],p2[3],1.0}; double l7 = (r4_t){p3[0],p3[1],p3[3],1.0}; double l8 = (r4_t){p4[0],p4[1],p4[3],1.0}; double l9 = (r4_t){p1[1],p1[2],p1[3],1.0}; double l10 = (r4_t){p2[1],p2[2],p2[3],1.0}; double l11 = (r4_t){p3[1],p3[2],p3[3],1.0}; double l12 = (r4_t){p4[1],p4[2],p4[3],1.0}; double l13 = (r4_t){p1[0],p1[2],p1[3],1.0}; double l14 = (r4_t){p2[0],p2[2],p2[3],1.0}; double l15 = (r4_t){p3[0],p3[2],p3[3],1.0}; double l16 = (r4_t){p4[0],p4[2],p4[3],1.0} ){ d1 = r4_det(l1,l2,l3,l4); d2 = r4_det(l5,l6,l7,l8); d3 = r4_det(l9,l10,l11,l12); d4 = r4_det(l13,l14,l15,l16); vol = 1.0/6.0 * sqrt(d1*d1+d2*d2+d3*d3+d4*d4); return vol; } } CalVol; /* VAR p1,p2,p3,p4,A,B,C,n : r4_t; vol,vol1 : double; */ double *a,b,c,d; { a = 79.05; b = 201.45; c = 38.25; d = 142.8; fprintf(Stdio.stdout, Fmt.Int(ROUND(a)) & Fmt.Int(ROUND(b)) \ Fmt.Int(ROUND(c)) & Fmt.Int(ROUND(d)) & "\n"); /* p1 = (r4_t){ 1.000001, 1.000001, 1.00001, 1.00001}; p2 = (r4_t){ 3.000001, 3.000001, 3.00000, 3.00000}; p3 = (r4_t){-0.147001, -0.793001, 0.66301, -0.00002}; p4 = (r4_t){-0.000005, -0.677001, 0.70002, -0.27301}; vol = CalVol(p1,p2,p3,p4); fprintf(Stdio.stdout, "V. em funcao das coordenadas dos seus nodes extremos: " \ Fmt.LongReal(vol, Fmt.Style.Fix,prec = 2) & "\n"); A = r4_Sub(p2,p1); B = r4_Sub(p4,p1); C = r4_Sub(p3,p2); n = r4_cross(A,B,C); vol1 = 1.0/6.0 * r4_Norm(n); fprintf(Stdio.stdout, "V. em f. do produto vetorial dos nodes extremos: " \ Fmt.LongReal(vol1, Fmt.Style.Fix,prec = 2) & "\n"); */ } Volume. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/WhatAttributes.c #define PROG_NAME "WhatAttributes" #define PROG_DESC "???" #define PROG_VERS "1.0" #define WhatAttributes_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Program to find what type of geometric degeneration exists in a given arbitrary topology (triangulation or not). The "detail" option allows to print detail information about the degeneracies. Otherwise only an abstract information is printed. */ #define WhatAttributes_C_author \ "Created by L. Lozada, 1999-2000.\n" \ "Modified 2000-06-08: Including the number of original nodes\n" #include #include #include // #INCLUDE VAR nve,nee,nfe,npe: uint = 0; TYPE typedef struct Options_t { inFile: char *; bool_t detail; } /* Initial guess file name (minus ".tp") */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { /* Clean the marks for the attribute degenerate */ for (i = 0; i < top->node.ne; i++) { ??? vi = top->node[i]; { if (0 == strcmp(vi.label, "VV"))){ nve++;}; } } for (i = 0; i < top->NE; i++) { ??? ei = top->edge[i]; { if (ei->exists){ nee++;}; } } for (i = 0; i < top->wall.ne; i++) { ??? fi = top->wall[i]; { if (fi->exists){ nfe++;} } } for (i = 0; i < top->cell.ne; i++) { ??? pi = top->cell[i]; { if (pi->exists){ npe++;} } } fprintf(stderr, "there are "&Fmt.Int(nve)&" existing nodes\n"); fprintf(stderr, "there are "&Fmt.Int(nee)&" existing @{edge->?}s\n"); fprintf(stderr, "there are "&Fmt.Int(nfe)&" existing walls\n"); fprintf(stderr, "there are "&Fmt.Int(npe)&" existing cells\n"); } } DoIt; Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); o->detail = argparser_keyword_present(pp, "-detail"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: WhatAttributes" \ " -inFile [ -detail ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } WhatAttributes. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/WhatDegenerations.c { /* Program to find what type of geometric degeneration exists in a given arbitrary topology (triangulation or not). The "detail" option allows to print detail information about the degeneracies. Otherwise only an abstract information is printed. */ #define WhatDegenerations_C_author \ "Created by L. Lozada, 1999-2000.\n" \ "Modified by L.A.P.Lozada on 2000-02-07." // #INCLUDE // #INCLUDE #include #include // #INCLUDE #include CONST double INIT_STACK_SIZE = 1024; VAR Edge_vec_t estack = Edge_vec_new(INIT_STACK_SIZE); Edge_vec_t estackT = Edge_vec_new(INIT_STACK_SIZE); Edge_vec_t estackF = Edge_vec_new(INIT_STACK_SIZE); Wall_vec_t fstack = Wall_vec_new(INIT_STACK_SIZE); Wall_vec_t fstackT = Wall_vec_new(INIT_STACK_SIZE); Wall_vec_t fstackF = Wall_vec_new(INIT_STACK_SIZE); pstack = Cell_vec_new(INIT_STACK_SIZE); etop,etopT,etopF,ftop,ftopT,ftopF,ptop,eetop,fftop,pptop: uint = 0; TYPE typedef struct Options_t { inFile: char *; bool_t detail; } /* Initial guess file name (minus ".tp") */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) VAR bool_t @{edge->?}s,walls, cells = FALSE; e1,e2,f1,f2,p1,p2: REF ARRAY OF INTEGER; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFile); ??? top = tc.top; { /* Clean the marks for the attribute degenerate */ for (i = 0; i < top->NE; i++){ deg[i] = FALSE; } for (i = 0; i < top->NE; i++) { for (j = i+1; j < top->NE; j++) { ??? ei = NARROW(top->edge[i], Edge_t); { double ej = NARROW(top->edge[j], Edge_t); double ei0 = ei.node[0]->num; double ei1 = ei.node[1]->num; double ej0 = ej.node[0]->num; double ej1 = ej.node[1]->num ){ e1 = NEW(REF ARRAY OF INTEGER, 2); e1[0] = ei0; e1[1] = ei1; Mis.InsertionSort(1,e1); e2 = NEW(REF ARRAY OF INTEGER, 2); e2[0] = ej0; e2[1] = ej1; Mis.InsertionSort(1,e2); if ((e1[0] == e2[0]) && (e1[1] == e2[1])) { if (! deg[i]) { deg[i] = TRUE; estack.e[etop] = ei; etop++; if (ei->exists) { estackT[etopT] = ei; etopT++; } else { estackF[etopF] = ei; etopF++; } } if (! deg[j]) { deg[j] = TRUE; estack.e[etop] = ej; etop++; if (ej->exists) { estackT[etopT] = ej; etopT++; } else { estackF[etopF] = ej; etopF++; } } @{edge->?}s = TRUE; } } } } /* Clean the marks for the attribute degenerate */ for (i = 0; i < top->wall.ne; i++){ fdeg[i] = FALSE; } if (top->der == 3) { for (i = 0; i < top->wall.ne; i++) { for (j = i+1; j < top->wall.ne; j++) { ??? fi = top->wall[i]; ??? fj = top->wall[j]; ??? fi0 = fi.node^[0]->num; ??? fi1 = fi.node^[1]->num; ??? fi2 = fi.node^[2]->num; ??? fj0 = fj.node^[0]->num; ??? fj1 = fj.node^[1]->num; ??? fj2 = fj.node^[2]->num; { f1 = NEW(REF ARRAY OF INTEGER, 3); f1[0] = fi0; f1[1] = fi1; f1[2] = fi2; Mis.InsertionSort(2,f1); f2 = NEW(REF ARRAY OF INTEGER, 3); f2[0] = fj0; f2[1] = fj1; f2[2] = fj2; Mis.InsertionSort(2,f2); if ((f1[0] == f2[0]) && (f1[1] == f2[1]) && (f1[2] == f2[2])) { if (! fdeg[i]) { fdeg[i] = TRUE; fstack.e[ftop] = fi; ftop++; if (fi->exists) { fstackT[ftopT] = fi; ftopT++; } else { fstackF[ftopF] = fi; ftopF++; } } if (! fdeg[j]) { fdeg[j] = TRUE; fstack.e[ftop] = fj; ftop++; if (fj->exists) { fstackT[ftopT] = fj; ftopT++; } else { fstackF[ftopF] = fj; ftopF++; } } walls = TRUE; } } } } } else if (top->der == 4){ for (i = 0; i < top->wall.ne; i++) { for (j = i+1; j < top->wall.ne; j++) { ??? fi = top->wall[i]; ??? fj = top->wall[j]; ??? fi0 = fi.node^[0]->num; ??? fi1 = fi.node^[1]->num; ??? fi2 = fi.node^[2]->num; ??? fi3 = fi.node^[3]->num; ??? fj0 = fj.node^[0]->num; ??? fj1 = fj.node^[1]->num; ??? fj2 = fj.node^[2]->num; ??? fj3 = fj.node^[3]->num; { f1 = NEW(REF ARRAY OF INTEGER, 4); f1[0] = fi0; f1[1] = fi1; f1[2] = fi2; f1[3] = fi3; Mis.InsertionSort(3,f1); f2 = NEW(REF ARRAY OF INTEGER, 4); f2[0] = fj0; f2[1] = fj1; f2[2] = fj2; f2[3] = fj3; Mis.InsertionSort(3,f2); if (((f1[0] == f2[0]) && (f1[1] == f2[1]) && ((f1[2] == f2[2]) ) && (f1[3] == f2[3]))){ if (! fdeg[i]) { fdeg[i] = TRUE; fstack.e[ftop] = fi; ftop++; } if (! fdeg[j]) { fdeg[j] = TRUE; fstack.e[ftop] = fj; ftop++; } walls = TRUE; } } } } } else if (top->der == 2){ for (i = 0; i < top->wall.ne; i++) { for (j = i+1; j < top->wall.ne; j++) { ??? fi = top->wall[i]; ??? fj = top->wall[j]; ??? fi0 = fi.node^[0]->num; ??? fi1 = fi.node^[1]->num; ??? fj0 = fj.node^[0]->num; ??? fj1 = fj.node^[1]->num; { f1 = NEW(REF ARRAY OF INTEGER, 2); f1[0] = fi0; f1[1] = fi1; Mis.InsertionSort(1,f1); f2 = NEW(REF ARRAY OF INTEGER, 2); f2[0] = fj0; f2[1] = fj1; Mis.InsertionSort(1,f2); if ((f1[0] == f2[0]) && (f1[1] == f2[1])) { if (! fdeg[i]) { fdeg[i] = TRUE; fstack.e[ftop] = fi; ftop++; } if (! fdeg[j]) { fdeg[j] = TRUE; fstack.e[ftop] = fj; ftop++; } walls = TRUE; } } } } } /* Clean the marks for the attribute degenerate */ for (i = 0; i < top->cell.ne; i++){ pdeg[i] = FALSE; } if (top->der == 3) { for (i = 0; i < top->cell.ne; i++) { for (j = i+1; j < top->cell.ne; j++) { ??? pi = top->cell[i]; ??? pj = top->cell[j]; ??? pi0 = pi.node^[0]->num; ??? pi1 = pi.node^[1]->num; ??? pi2 = pi.node^[2]->num; ??? pi3 = pi.node^[3]->num; ??? pj0 = pj.node^[0]->num; ??? pj1 = pj.node^[1]->num; ??? pj2 = pj.node^[2]->num; ??? pj3 = pj.node^[3]->num; { p1 = NEW(REF ARRAY OF INTEGER, 4); p1[0] = pi0; p1[1] = pi1; p1[2] = pi2; p1[3] = pi3; Mis.InsertionSort(3,p1); p2 = NEW(REF ARRAY OF INTEGER, 4); p2[0] = pj0; p2[1] = pj1; p2[2] = pj2; p2[3] = pj3; Mis.InsertionSort(3,p2); if ((p1[0]==p2[0]) && (p1[1]==p2[1]) && ((p1[2]==p2[2]) AND (p1[3]==p2[3]))){ if (! pdeg[i]) { pdeg[i] = TRUE; pstack.e[ptop] = pi; ptop++; } if (! pdeg[j]) { pdeg[j] = TRUE; pstack.e[ptop] = pj; ptop++; } cells = TRUE; } } } } } else if (top->der == 4){ for (i = 0; i < top->cell.ne; i++) { for (j = i+1; j < top->cell.ne; j++) { ??? pi = top->cell[i]; ??? pj = top->cell[j]; ??? pi0 = pi.node^[0]->num; ??? pi1 = pi.node^[1]->num; ??? pi2 = pi.node^[2]->num; ??? pi3 = pi.node^[3]->num; ??? pi4 = pi.node^[4]->num; ??? pi5 = pi.node^[5]->num; ??? pi6 = pi.node^[6]->num; ??? pi7 = pi.node^[7]->num; ??? pj0 = pj.node^[0]->num; ??? pj1 = pj.node^[1]->num; ??? pj2 = pj.node^[2]->num; ??? pj3 = pj.node^[3]->num; ??? pj4 = pj.node^[4]->num; ??? pj5 = pj.node^[5]->num; ??? pj6 = pj.node^[6]->num; ??? pj7 = pj.node^[7]->num; { p1 = NEW(REF ARRAY OF INTEGER, 8); p1[0] = pi0; p1[1] = pi1; p1[2] = pi2; p1[3] = pi3; p1[4] = pi4; p1[5] = pi5; p1[6] = pi6; p1[7] = pi7; Mis.InsertionSort(7,p1); p2 = NEW(REF ARRAY OF INTEGER, 8); p2[0] = pj0; p2[1] = pj1; p2[2] = pj2; p2[3] = pj3; p2[4] = pj4; p2[5] = pj5; p2[6] = pj6; p2[7] = pj7; Mis.InsertionSort(7,p2); IF( (p1[0]==p2[0])) && ((p1[1]==p2[1]) AND (p1[2]==p2[2])) && ((p1[3]==p2[3]) AND (p1[4]==p2[4])) && ((p1[5]==p2[5]) AND (p1[6]==p2[6])) && (p1[7]==p2[7]) )){ if (pdeg[i]) { pstack.e[ptop] = pi; ptop++; } if (pdeg[j]) { pdeg[j] = TRUE; pstack.e[ptop] = pj; ptop++; } cells = TRUE; } } } } } if (@{edge->?}s) { fprintf(stderr, "there are " & Fmt.Int(etop) & " @{edge->?} degeneracies:\n"); fprintf(stderr, " " & Fmt.Int(etopT) & " existing\n"); fprintf(stderr, " " & Fmt.Int(etopF) & " not existing\n"); assert(etop == etopF + etopT); if (o->detail) { fprintf(stderr, "---------------------------------\n"); fprintf(stderr, " @{edge->?} node node\n"); eetop = etop; while (eetop > 0) { eetop = eetop-1; ??? @{edge->?} = estack.e[eetop]; ??? en = @{edge->?}->num; ??? a = @{edge->?}.pa; Node_t v0 = OrgV(a)->num; ??? v1 = OrgV(Clock(a))->num; { fprintf(stderr, Fmt.Pad(Fmt.Int(en), 4) & ":"); fprintf(stderr, Fmt.Pad(Fmt.Int(v0), 6) & " "); fprintf(stderr, Fmt.Pad(Fmt.Int(v1), 6) & "\n"); } } } } else { fprintf(stderr, "there aren't @{edge->?} degeneracies\n"); } if (walls) { fprintf(stderr, "there are "&Fmt.Int(ftop)&" wall degeneracies:\n"); fprintf(stderr, " " & Fmt.Int(ftopT) & " existing\n"); fprintf(stderr, " " & Fmt.Int(ftopF) & " not existing\n"); assert(ftop == ftopF + ftopT); if (o->detail) { fprintf(stderr, "---------------------------------\n"); fprintf(stderr, " wall @{edge->?} @{edge->?} @{edge->?}\n"); fftop = ftop; while (fftop > 0) { fftop = fftop-1; ??? wall = fstack.e[fftop]; ??? fn = wall->num; ??? a = wall.pa; Place_t b = NextE(a); Place_t c = NextE(b); ??? e0 = PEdge(a)->num; ??? e1 = PEdge(b)->num; ??? e2 = PEdge(c)->num; ??? i0 = ScanStack@{Edge->?}(e0); ??? i1 = ScanStack@{Edge->?}(e1); ??? i2 = ScanStack@{Edge->?}(e2); { fprintf(stderr, Fmt.Pad(Fmt.Int(fn), 3) & ":"); if (i0) { fprintf(stderr, Fmt.Pad(Fmt.Int(e0), 6) & "T"); } else { fprintf(stderr, Fmt.Pad(Fmt.Int(e0), 6) & "F"); } if (i1) { fprintf(stderr, Fmt.Pad(Fmt.Int(e1), 6)& "T"); } else { fprintf(stderr, Fmt.Pad(Fmt.Int(e1), 6) & "F"); } if (i2) { fprintf(stderr, Fmt.Pad(Fmt.Int(e2), 6) & "T\n"); } else { fprintf(stderr, Fmt.Pad(Fmt.Int(e2), 6) & "F\n"); } } } } } else { fprintf(stderr, "there aren't wall degeneracies\n"); } if (cells) { fprintf(stderr, "there are "&Fmt.Int(ptop)&" cell degeneracies\n"); if (o->detail) { fprintf(stderr, "-------------------------------------\n"); fprintf(stderr, "poly wall wall wall wall\n"); pptop = ptop; while (pptop > 0) { pptop = pptop-1; ??? cell = pstack.e[pptop]; ??? np = cell->num; ??? p = Srot(top->cell[np]); Place_t a = Tors(p); ??? walls = Triangulation.TetraWalls(a); ??? f0 = walls[0]->num; ??? f1 = walls[1]->num; ??? f2 = walls[2]->num; ??? f3 = walls[3]->num; ??? i0 = ScanStackWall(f0); ??? i1 = ScanStackWall(f1); ??? i2 = ScanStackWall(f2); ??? i3 = ScanStackWall(f3); { fprintf(stderr, Fmt.Pad(Fmt.Int(np), 3) & ":"); if (i0) { fprintf(stderr, Fmt.Pad(Fmt.Int(f0), 6) & "T"); } else { fprintf(stderr, Fmt.Pad(Fmt.Int(f0), 6) & "F"); } if (i1) { fprintf(stderr, Fmt.Pad(Fmt.Int(f1), 6) & "T"); } else { fprintf(stderr, Fmt.Pad(Fmt.Int(f1), 6) & "F"); } if (i2) { fprintf(stderr, Fmt.Pad(Fmt.Int(f2), 6) & "T"); } else { fprintf(stderr, Fmt.Pad(Fmt.Int(f2), 6) & "F"); } if (i3) { fprintf(stderr, Fmt.Pad(Fmt.Int(f3), 6) & "T\n"); } else { fprintf(stderr, Fmt.Pad(Fmt.Int(f3), 6) & "F\n"); } } } } } else { fprintf(stderr, "there aren't cell degeneracies\n"); } } } DoIt; void FindDegeneracies(ElemTableRec_t *top) /* Finds geometric degeneracies. Update the attribute "degenerate" of the elements: @{edge->?}, wall and cell. */ Edge_vec_t estack = Edge_vec_new(top->NE); bool_vec_t edeg = bool_vec_new(top->NE); Wall_vec_t fstack = Wall_vec_new(top->wall.ne); bool_vec_t fdeg = bool_vec_new(top->wall.ne); pstack = NEW(REF ARRAY OF Cell, top->cell.ne); bool_vec_t pdeg = bool_vec_new(top->cell.ne); etop,ftop,ptop: uint = 0; { Find@{Edge->?}Degeneracies(top, estack^, etop); FindWallDegeneracies(top, fstack^, ftop); FindCellDegeneracies(top-> pstack^, ptop); } /* END FindDegeneracies */ PROCEDURE Find@{Edge->?}Degeneracies(ElemTableRec_t *top, Edge_vec_t estack; VAR uint *etop; ) == /* Find @places of @{edge->?}s with same nodes. */ { etop = 0; for (i = 0; i < top->NE; i++){ edeg[i] = FALSE; } for (i = 0; i < top->NE; i++) { ??? ei = top->edge[i]; with ( @{Edge->?}, double ei0 = OrgV(ei)->num; double ei1 = OrgV(Clock(ei))->num) { for (j = i+1; j < top->NE; j++) { ??? ej = top->edge[j]; Node_t ej0 = OrgV(ej)->num; ??? ej1 = OrgV(Clock(ej))->num; { if (((ei0 == ej0) && (ei1 == ej1) ) || ((ei0 == ej1) && (ei1 == ej0))){ if (! deg[i]) { deg[i] = TRUE; estack.e[etop] = ei; etop++; } if (! deg[j]) { deg[j] = TRUE; estack.e[etop] = ej; etop++; } } } } } } } /* END Find@{Edge->?}Degeneracies */ PROCEDURE FindWallDegeneracies(ElemTableRec_t *top, Wall_vec_t fstack; VAR uint *ftop; ) /* Find @places of walls with same nodes */ rvfi, rvfj: REF uint_vec_t; uint dgi, dgj; { ftop = 0; for (i = 0; i < top->wall.ne; i++){ fdeg[i] = FALSE; } for (i = 0; i < top->wall.ne; i++) { CollectWallNodes(top->wall[i], rvfi, dgi); ??? fi = top->wall[i], vfi == SUBARRAY(rvfi^, 0, dgi); { Mis.SortCardinals(vfi); for (j = i+1; j < top->wall.ne; j++) { CollectWallNodes(top->wall[j], rvfj, dgj); ??? fj = top->wall[j], vfj == SUBARRAY(rvfj^, 0, dgj); { Mis.SortCardinals(vfj); if (vfi == vfj) { if (! fdeg[i]) { fdeg[i] = TRUE; fstack.e[ftop] = fi; ftop++; } if (! fdeg[j]) { fdeg[j] = TRUE; fstack.e[ftop] = fj; ftop++; } } } } } } } /* END FindWallDegeneracies */ PROCEDURE FindCellDegeneracies(ElemTableRec_t *top, ARRAY OF Cell pstack ; uint *ptop; ) /* Finds @places of cells with same nodes. */ rvpi, rvpj: REF uint_vec_t; uint dgi, dgj; { ptop = 0; for (i = 0; i < top->cell.ne; i++){ pdeg[i] = FALSE; } ClearXMarks(top); for (i = 0; i < top->cell.ne; i++) { Place_t ai = Tors(Srot(top.cell[i])), pi == PnegP(ai); { assert(pi->num == i); CollectCellNodes(ai, rvpi, dgi); ??? vpi = SUBARRAY(rvpi^, 0, dgi); { Mis.SortCardinals(vpi); for (j = i+1; j < top->cell.ne; j++) { Place_t aj = Tors(Srot(top->cell[j])), pj == PnegP(aj); { assert(pj->num == j); CollectCellNodes(aj, rvpj, dgj); ??? vpj = SUBARRAY(rvpj^, 0, dgj); { Mis.SortCardinals(vpj); if (vpi == vpj) { if (! pdeg[i]) { pdeg[i] = TRUE; pstack.e[ptop] = pi; ptop++; } if (! pdeg[j]) { pdeg[j] = TRUE; pstack.e[ptop] = pj; ptop++; } } } } } } } } } /* END FindDegenerateCells */ Options_t *GetOptions(int argc, char **argv) { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-inFile"); o->inFile = argparser_get_next(pp); o->detail = argparser_keyword_present(pp, "-detail"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: WhatDegenerations" \ " -inFile [ -detail ]\n"); END¦ } } return o; } /* END GetOptions */ PROCEDURE ScanStack@{Edge->?}(uint n): bool_t == uint counter = 0; { counter = etop; while (counter > 0) { counter = counter-1; if (estack.e[counter]->num == n){ return TRUE; } } return FALSE; } /* END ScanStack@{Edge->?} */ bool_t ScanStackWall(num: uint) uint counter = 0; { counter = ftop; while (counter > 0) { counter = counter-1; if (fstack.e[counter]->num == num){ return TRUE; } } return FALSE; } /* END ScanStackWall */ { DoIt() } WhatDegenerations. /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Deps.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libenergy/Makefile // #TIMESTAMP # Last edited on 2007-01-23 12:03:06 by stolfi LIBNAME := libenergy include ../../GENERIC-LIB.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/Deps.make Bary.ho: Bary.h Bary.ho: ../liboct/Octf.ho Bary.ho: ../liboct/Triangulation.ho Refine.ho: Refine.h Refine.ho: ../liboct/Octf.ho Refine.ho: ../liboct/Triangulation.ho Refine.ho: /home/staff/stolfi/PUB/include/vec.ho Bary.o: Bary.c Bary.o: Bary.h Bary.o: ../liboct/Triangulation.ho Bary.o: ../liboct/Octf.ho Bary.o: ../liboct/OctfRep.ho Bary.o: /home/staff/stolfi/PUB/include/affirm.ho Refine.o: Refine.c Refine.o: Refine.h Refine.o: /home/staff/stolfi/PUB/include/r3.ho Refine.o: ../liboct/Squared.ho Refine.o: ../liboct/Octf.ho Refine.o: ../liboct/Triangulation.ho // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/libmore/Makefile // #TIMESTAMP # Last edited on 2007-01-25 14:48:03 by stolfi LIBNAME := libmore OTHERINCS := \ ../liboct include ../../GENERIC-LIB.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Deps.make Minimizer.ho: Minimizer.h Mis.ho: Mis.h Mis.ho: Random.h Mis.ho: /home/staff/stolfi/PUB/include/r2.ho Mis.ho: /home/staff/stolfi/PUB/include/r3.ho Mis.ho: /home/staff/stolfi/PUB/include/r4.ho Octf.ho: Octf.h Octf.ho: /home/staff/stolfi/PUB/include/r3.ho Octf.ho: /home/staff/stolfi/PUB/include/vec.ho Octf.ho: /home/staff/stolfi/PUB/include/bool.ho Octf.ho: /home/staff/stolfi/PUB/include/frgb.ho OctfData.ho: OctfData.h OctfData.ho: Octf.h OctfData.ho: OctfRep.h OctfData.ho: /home/staff/stolfi/PUB/include/vec.ho OctfData.ho: /home/staff/stolfi/PUB/include/bool.ho OctfRep.ho: OctfRep.h OctfRep.ho: Octf.h OctfRep.ho: /home/staff/stolfi/PUB/include/vec.ho OctfRep.ho: /home/staff/stolfi/PUB/include/bool.ho PZGeo3.ho: PZGeo3.h PZGeo3.ho: /home/staff/stolfi/PUB/include/r3.ho PZGeo4.ho: PZGeo4.h PZGeo4.ho: /home/staff/stolfi/PUB/include/r4.ho ParseMinimizerParams.ho: ParseMinimizerParams.h ParseMinimizerParams.ho: /home/staff/stolfi/PUB/include/argparser.ho ParseMinimizerParams.ho: Minimizer.h Pov.ho: Pov.h Pov.ho: /home/staff/stolfi/PUB/include/r3.ho Random.ho: Random.h Random.ho: /home/staff/stolfi/PUB/include/jsrandom.ho Refine.ho: Refine.h Refine.ho: Triangulation.h Squared.ho: Squared.h Squared.ho: /home/staff/stolfi/PUB/include/r4.ho Squared.ho: Triangulation.h Tools.ho: Tools.h Tools.ho: Triangulation.h Tools.ho: Octf.h Triangulation.ho: Triangulation.h Triangulation.ho: /home/staff/stolfi/PUB/include/r4.ho Triangulation.ho: /home/staff/stolfi/PUB/include/r3.ho Triangulation.ho: Random.h Triangulation.ho: Octf.h Triangulation.ho: OctfData.h Tridimensional.ho: Tridimensional.h Tridimensional.ho: /home/staff/stolfi/PUB/include/r3x3.ho Tridimensional.ho: Triangulation.h Tridimensional.ho: /home/staff/stolfi/PUB/include/r4.ho Tridimensional.ho: /home/staff/stolfi/PUB/include/r3.ho JSTriRest.o: JSTriRest.c // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/liboct/Makefile // #TIMESTAMP # Last edited on 2007-01-25 14:47:39 by stolfi LIBNAME := liboct OTHERINCS := \ ../libmore include ../../GENERIC-LIB.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/Deps.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-main/Makefile // #TIMESTAMP # Last edited on 2007-01-25 14:53:11 by stolfi PROGS := ${basename ${wildcard *.c}} OTHERINCS := \ ../liboct include ../../GENERIC-PROGS.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Deps.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #FILE cur/progs-more/Makefile // #TIMESTAMP # Last edited on 2007-01-23 14:39:33 by stolfi PROGS := ${basename ${wildcard *.c}} include ../../GENERIC-PROGS.make // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~