root/cgm/geom/Cholla/Cholla.h

Revision 1040, 27.5 kB (checked in by tautges, 2 years ago)

Version 10.2 of cgm.

Line 
1 /** \file Cholla.h
2     
3 //- Class:       Cholla
4 //- Description: C-style Interface for the Cholla module
5 //-              Facet-based geometry definition and evaluation
6 //- Owner:       Steven J. Owen
7 //- Checked by:
8 //- Version:
9 */
10
11 #ifndef CHOLLA____H
12 #define CHOLLA____H
13
14 #define NUM_EDGE_CPTS 3
15 #define NUM_TRI_CPTS  6
16 #define NUM_QUAD_CPTS 15
17
18 #include "CubitDefines.h"
19 /**
20  * Return control points for a quartic Bezier for each face, using
21  * a given feature angle tolerance to distinguish C0 and C1 edges.
22  * Separate arrays of tris and quad faces should be supplied
23  *
24  * @param angle         - (IN) feature angle tolerance (degrees)
25  * @param numTri        - (IN) number of quad faces
26  * @param numQuad       - (IN) number of triangle faces
27  * @param numEdge       - (IN) number of edges
28  * @param numVert       - (IN) number of vertices
29  * @param triEdge       - (IN) array of face to edge numbering,
30  *                             length 3 * numTri
31  * @param quadEdge      - (IN) array of face to edge numbering,
32  *                             length 4 * numQuad
33  * @param edgeVert      - (IN) array of edge to vertex numbering,
34  *                             length 2*numEdge
35  * @param vert          - (IN) array of vertex coordinates,
36  *                             length 3*numVert
37  * @param edgeCtrlPts   - (OUT) array of control points computed at the edges
38  *                              length 3*(3*numEdge)
39  * @param triCtrlPts    - (OUT) array of control points computed at the triangles
40  *                              length 3*(6*numTri)
41  * @param quadCtrlPts   - (OUT) array of control points computed at the quads
42  *                              length 3*(15*numQuad)
43  */
44 void constructBezier( double angle, int numTri, int numQuad, int numEdge,
45                       int numVert, int* triEdge, int* quadEdge,
46                       int* edgeVert, double* vert,
47                       double* edgeCtrlPts, double* triCtrlPts,
48                       double* quadCtrlPts );
49
50 /**
51  * Return normal and tangents for on a list of triangles
52  * a given feature angle tolerance to distinguish C0 and C1 edges.
53  * Separate arrays of tris and quad faces should be supplied
54  *
55  * @param angle         - (IN) feature angle tolerance (degrees)
56  * @param numTri        - (IN) number of tri faces
57  * @param numEdge       - (IN) number of edges
58  * @param numVert       - (IN) number of vertices
59  * @param triEdge       - (IN) array of face to edge numbering,
60  *                             length 3 * numTri
61  * @param edgeVert      - (IN) array of edge to vertex numbering,
62  *                             length 2*numEdge
63  * @param vert          - (IN) array of vertex coordinates,
64  *                             length 3*numVert
65  * @param triVertNorms  - (OUT) array of normals at the triangle vertices
66  *                              length 3*(3*numTri)
67  * @param edgeVertTang  - (OUT) array of tangents at the edge vertices
68  *                              length 3*(2*numEdge)
69  * @param edgeTypeFlags - (OUT) array of flags labeling the type of each edge,
70  *                              length numEdge \n
71  *                              2 = non-manifold edge \n
72  *                              1 = concave feature edge \n
73  *                              0 = non-feature edge \n
74  *                              -1= convex feature edge \n
75  */
76 void constructTriNormals( double angle, int numTri, int numEdge,
77                           int numVert, int* triEdge,
78                           int* edgeVert, double* vert,
79                           double* triVertNorms, double* edgeVertTang,
80                           int* edgeTypeFlags);
81
82 /**
83  * Return normal and tangents for on a list of quad faces
84  * a given feature angle tolerance to distinguish C0 and C1 edges.
85  * Separate arrays of tris and quad faces should be supplied
86  *
87  * @param angle         - (IN) feature angle tolerance (degrees)
88  * @param numQuad       - (IN) number of quad faces
89  * @param numEdge       - (IN) number of edges
90  * @param numVert       - (IN) number of vertices
91  * @param quadEdge      - (IN) array of face to edge numbering,
92  *                             length 4 * numQuad
93  * @param edgeVert      - (IN) array of edge to vertex numbering,
94  *                             length 2*numEdge
95  * @param vert          - (IN) array of vertex coordinates,
96  *                             length 3*numVert
97  * @param quadVertNorms - (OUT) array of normals at the quad vertices
98  *                              length 3*(4*numQuad)
99  * @param edgeVertTang  - (OUT) array of tangents at the edge vertices
100  *                              length 3*(2*numEdge)
101  * @param edgeTypeFlags - (OUT) array of flags labeling the type of each edge,
102  *                              length numEdge \n
103  *                              2 = non-manifold edge \n
104  *                              1 = concave feature edge \n
105  *                              0 = non-feature edge \n
106  *                              -1= convex feature edge \n
107  */
108 void constructQuadNormals( double angle, int numQuad, int numEdge,
109                            int numVert, int* quadEdge,
110                            int* edgeVert, double* vert,
111                            double* quadVertNorms, double* edgeVertTang,
112                            int* edgeTypeFlags);
113
114 /**
115  * Return normal and tangents for on a list of triangles
116  * a given  a file containing the geometric normals and tangents.
117  * Separate arrays of tris and quad faces should be supplied
118  *
119  * @param filename      - (IN) full path and name of the text file containing
120  *                             the geometric surface normals and tangents.
121  *                             This file is output from Cubit when exporting
122  *                             an exodus file.
123  * @param numTri        - (IN) number of tri faces
124  * @param triVert       - (IN) array of face to vertex numbering,
125  *                             length 3 * numTri
126  * @param triVertNorms  - (OUT) array of normals at the triangle vertices
127  *                              length 3*(3*numTri)
128  * @param edgeVertTang  - (OUT) array of tangents at the edge vertices
129  *                              length 3*(2*numEdge)
130  */
131 CubitStatus constructTriNormalsFromFile( const char *filename,
132                                          int numTri,
133                                          int numEdge,
134                                          int* triEdge,
135                                          int* edgeVert,
136                                          double* triVertNorms,
137                                          double* edgeVertTang );
138
139 /**
140  * Return normal and tangents for on a list of quad faces
141  * a given a file containing the geometric normals and tangents.
142  * Separate arrays of tris and quad faces should be supplied
143  *
144  * @param filename      - (IN) full path and name of the text file containing
145  *                             the geometric surface normals and tangents.
146  *                             This file is output from Cubit when exporting
147  *                             an exodus file.
148  * @param numQuad       - (IN) number of quad faces
149  * @param numEdge       - (IN) number of edges
150  * @param quadEdge      - (IN) array of face to edge numbering,
151  *                             length 4 * numQuad
152  * @param edgeVert      - (IN) array of edge to vertex numbering,
153  *                             length 2*numEdge
154  * @param quadVertNorms - (OUT) array of normals at the quad vertices
155  *                              length 3*(4*numQuad)
156  * @param edgeVertTang  - (OUT) array of tangents at the edge vertices
157  *                              length 3*(2*numEdge)
158  */
159 CubitStatus constructQuadNormalsFromFile( const char *filename,
160                                           int numQuad,
161                                           int numEdge,
162                                           int* quadEdge,
163                                           int* edgeVert,
164                                           double* quadVertNorms,
165                                           double* edgeVertTang );
166
167 /**
168  * Return normal and tangents for on a list of quad faces
169  * a given a file containing the geometric normals and tangents.
170  * This returns all of the data in the file rather than just for the
171  * specified input elements and edges like constructQuadNormalsFromFile
172  * and constructTriNormalsFromFile
173  *
174  * @param filename      - (IN) full path and name of the text file containing
175  *                             the geometric surface normals and tangents.
176  *                             This file is output from Cubit when exporting
177  *                             an exodus file.
178  * @param numTri        - (OUT) number of quad faces
179  * @param numQuad       - (OUT) number of quad faces
180  * @param numEdge       - (OUT) number of edges
181  * @param edgeVert      - (OUT) array of vertices on each edge.
182  *                              length 2*numEdge (Must be freed by caller)
183  * @param edgeVertTang  - (OUT) array of tangents at the edge vertices
184  *                              length 3*(2*numEdge) (Must be freed by caller)
185  * @param TriVert       - (OUT) array of vertices on each tri.
186  *                              length 3*numTri
187  * @param TriVertNorms  - (OUT) array of normals at the tri vertices
188  *                              length 3*(4*numTri) (Must be freed by caller)
189  * @param QuadVert      - (OUT) array of vertices on each quad.
190  *                              length 3*numQuad
191  * @param QuadVertNorms - (OUT) array of normals at the quad vertices
192  *                              length 3*(4*numQuad) (Must be freed by caller)
193  */
194 CubitStatus readMBGNormalFile( const char *filename,
195                                int *numTri,
196                                int *numQuad,
197                                int *numEdge,
198                                int **edgeVert,
199                                double **edgeVertTang,
200                                int **triVert,
201                                double **triVertNorms,
202                                int **quadVert,
203                                double **quadVertNorms );
204
205 /**
206  * Evaluate a set of quartic Bezier patches at a specified parametric location
207  * given its control points. Evaluates location, normal and/or derivative.
208  * Expects list of either quads or tris (not both)
209  *
210  * @param numFace       - (IN) number of faces to evaluate
211  * @param numEdge       - (IN) number of edges on the faces
212  * @param numVert       - (IN) number of vertices
213  * @param numVertPerFace- (IN) has value of of 3 or 4, for tris or quads
214  * @param faceEdge      - (IN) array of face to edge indecies (into edgeVert)
215  *                             length numVertPerFace * numFace
216  * @param edgeVert      - (IN) array of edge to vertex indecies (into vert)
217  *                             length 2 * numEdge
218  * @param vert          - (IN) array of vertex locations
219  *                             length 3 * numVert
220  * @param faceCtrlPts   - (IN) array of control points for the faces (same
221  *                             order as faceEdge)
222  *                             if (numFacePerVert == 3) ncp = 6
223  *                             if (numFacePerVert == 4) ncp = 15
224  *                             length = 3 * (ncp * numFace)
225  * @param edgeCtrlPts   - (IN) array of control points for the edges (same
226  *                             order as edgeVert array)
227  *                             length 3 * (3 * numEdge)
228  * @param numLocs       - (IN) number of locations to evaluate per face
229  * @param paramLocation - (IN) parametric location to evaluate on each face
230  *                             if (numFacePerVert == 3) (u,v,w)
231  *                               length = 3 * numLocs 
232  *                             if (numFacePerVert == 4) (u,v)
233  *                               length = 2 * numLocs
234  * @param location      - (OUT) evaluated point on surface at paramLocation
235  *                              length = numFace * 3 * numLocs
236  * @param normal        - (IN/OUT) evaluated normal at parmLocation. If NULL
237  *                              then will not be evaluated. Return vector
238  *                              is normalized
239  *                              length = numFace * 3 * numLocs
240  * @param deriv         - (IN/OUT) evaluated derivative at parmLocation with
241  *                              respect to uv or uvw system. If NULL
242  *                              then will not be evaluated.
243  *                              if (numFacePerVert == 3)
244  *                                length = numFace * numLocs * 3*3
245  *                                             (du/dx,du/dy,du/dz,
246  *                                              dv/dx,dv/dy,dv/dz,
247  *                                              dw/dx,dw/dz,dw/dz)
248  *                              if (numFacePerVert == 4)
249  *                                length = numFace * numLocs * 3*2
250  *                                             (du/dx,du/dy,du/dz,
251  *                                              dv/dx,dv/dy,dv/dz)                         
252  */
253 void evalBezierFace( int numFace, int numEdge, int numVert, int numVertPerFace,
254                      int* faceEdge, int* edgeVert,
255                      double* vert,  double* faceCtrlPts,
256                      double* edgeCtrlPts,
257                      int numLocs, double* paramLocation,
258                      double* location, double* normal, double* deriv );
259
260 /**
261  * This is the same as the evalBezierFace except it differes by the input
262  * arguments.  This function takes a list of normals and tangents at the face
263  * vertices and computes bezier control points internally.  Normals and tangents
264  * should have been computed previously in constructTriNormals
265  * or constructQuad Normals.  This function is not as computationally efficient
266  * as evalBezierFace since it requires Bezier control points to be computed
267  * as part of the call - however, it is more memory efficient, requiring fewer
268  * variables to be stored with the calling application. The following argument
269  * list describes only those arguments that differ from evalBezierFace above.
270  *
271  * @param vertNorms -     (IN) array of normals at the face vertices
272  *                              length 3*(numVertPerFace*numFace)
273  * @param edgeVertTang  - (OUT) array of tangents at the edge vertices
274  *                              length 3*(2*numEdge)
275  */
276 void evalBezierFaceFromNorms( int numFace, int numEdge, int numVert,
277                               int numVertPerFace, int* faceEdge, int* edgeVert,
278                               double* vert, double* vertNorms, double* edgeVertTang,
279                               int numLocs, double* paramLocation,
280                               double* location, double* normal, double* deriv );
281
282 /**
283  * Project a set of x-y-z locations to Bezier patches.  Finds the closest point on
284  * one of the patches.  Evaluates location, normal and/or derivative.
285  * Expects list of either quads or tris (not both)
286  *
287  * @param numFace       - (IN) number of faces to evaluate
288  * @param numEdge       - (IN) number of edges on the faces
289  * @param numVert       - (IN) number of vertices
290  * @param numVertPerFace- (IN) has value of of 3 or 4, for tris or quads
291  * @param faceEdge      - (IN) array of face to edge indecies (into edgeVert)
292  *                             length numVertPerFace * numFace
293  * @param edgeVert      - (IN) array of edge to vertex indecies (into vert)
294  *                             length 2 * numEdge
295  * @param vert          - (IN) array of vertex locations
296  *                             length 3 * numVert
297  * @param faceCtrlPts   - (IN) array of control points for the faces (same
298  *                             order as faceEdge)
299  *                             if (numFacePerVert == 3) ncp = 6
300  *                             if (numFacePerVert == 4) ncp = 15
301  *                             length = 3 * (ncp * numFace)
302  * @param edgeCtrlPts   - (IN) array of control points for the edges (same
303  *                             order as edgeVert array)
304  *                             length 3 * (3 * numEdge)
305  * @param numLocs       - (IN) number of locations to evaluate per face
306  * @param xyz           - (IN) xyz locations to evaluate on each face                             
307  *                               length = 3 * numLocs                             
308  * @param specify_tol   - (IN) 1 = a converge_tol is specified,
309  *                             0 = a converge_tol is not specified.  A default
310  *                                 tol will be computed and used.
311  * @param converge_tol  - (IN) The convergance tolerance for this projection.
312  *                             Will be ignored if specify_tol == 0
313  * @param xyzOnFace     - (OUT) locations on patches closest to input points xyz.
314  *                              length = 3 * numLocs
315  * @param normal        - (IN/OUT) evaluated normals at xyz. If NULL
316  *                              then will not be evaluated. Return vector
317  *                              is normalized
318  *                              length = 3 * numLocs
319  * @param deriv         - (IN/OUT) evaluated derivatives at xyz with
320  *                              respect to uv or uvw system. If NULL
321  *                              then will not be evaluated.
322  *                              if (numFacePerVert == 3)
323  *                                length = numLocs * 3*3
324  *                                             (du/dx,du/dy,du/dz,
325  *                                              dv/dx,dv/dy,dv/dz,
326  *                                              dw/dx,dw/dz,dw/dz)
327  *                              if (numFacePerVert == 4)
328  *                                length = numLocs * 3*2
329  *                                             (du/dx,du/dy,du/dz,
330  *                                              dv/dx,dv/dy,dv/dz)                         
331  */
332 void projToBezierFace( int numFace, int numEdge, int numVert, int numVertPerFace,
333                      int* faceEdge, int* edgeVert,
334                      double* vert,  double* faceCtrlPts,
335                      double* edgeCtrlPts,
336                      int numLocs, double* xyz,
337                      int specify_tol, double converge_tol,
338                      double* xyzOnFace, double* normal, double* deriv );
339
340 /**
341  * This is the same as the projToBezierFace except it differes by the input
342  * arguments.  This function takes a list of normals and tangents at the face
343  * vertices and computes bezier control points internally.  Normals and tangents
344  * should have been computed previously in constructTriNormals
345  * or constructQuadNormals.  This function is not as computationally efficient
346  * as evalBezierFace since it requires Bezier control points to be computed
347  * as part of the call - however, it is more memory efficient, requiring fewer
348  * variables to be stored with the calling application. The following argument
349  * list describes only those arguments that differ from projToBezierFace above.
350  *
351  * @param vertNorms -     (IN) array of normals at the face vertices
352  *                              length 3*(numVertPerFace*numFace)
353  * @param edgeVertTang  - (OUT) array of tangents at the edge vertices
354  *                              length 3*(2*numEdge)
355  */
356 void projToBezierFaceFromNorms( int numFace, int numEdge, int numVert, int numVertPerFace,
357                      int* faceEdge, int* edgeVert,
358                      double* vert,  double* vertNorms,
359                      double* edgeVertTang,
360                      int numLocs, double* xyz,
361                      int specify_tol, double converge_tol,
362                      double* xyzOnFace, double* normal, double* deriv );
363
364 /**
365  * Evaluate a quartic Bezier curve at a specified parametric location
366  * given its tangents at the end-points. Evaluates location,
367  * and/or tangent.
368  *
369  * @param numEdge       - (IN) number of edges on the faces
370  * @param numVert       - (IN) number of vertices
371  * @param edgeVert      - (IN) array of edge to vertex indecies (into vert)
372  *                             length 2 * numEdge
373  * @param vert          - (IN) array of vertex locations
374  *
375  * @param edgeVertTang  - (IN) array of tangents at the edge vertices
376  *                              length 3*(2*numEdge)
377  * @param numLocs       - (IN) number of locations to evaluate per edge
378  * @param paramLocation - (IN) parametric location to evaluate on each edge
379  *                             length = numLocs
380  * @param location      - (OUT) evaluated point on edge at paramLocation
381  *                              length = numEdge * 3 * numLocs
382  * @param tangent       - (IN/OUT) evaluated tangent at parmLocation. If NULL
383  *                              then will not be evaluated. Return vector
384  *                              is normalized
385  *                              length = numEdge * 3 * numLocs               
386  */
387 void evalBezierEdgeFromTans( int numEdge, int numVert, int* edgeVert,
388                               double* vert, double* edgeVertTang,
389                               int numLocs, double* paramLocation,
390                               double* location, double* tangent );
391 /**
392  * Evaluate a quartic Bezier curve at a specified parametric location
393  * given its control points. Evaluates location, and/or tangent.
394  *
395  * @param numEdge       - (IN) number of edges on the faces
396  * @param numVert       - (IN) number of vertices
397  * @param edgeVert      - (IN) array of edge to vertex indecies (into vert)
398  *                             length 2 * numEdge
399  * @param vert          - (IN) array of vertex locations
400  *                             length 3 * numVert
401  * @param edgeCtrlPts   - (IN) array of control pt locations for each edge in
402  *                              the bezier.  The beziers are quartic, so there
403  *                              are 3 control pts per curve in addition to the
404  *                              2 end pts for each curve for a total of 5 pts
405  *                              per edge.
406  *                              length = 3 * ( 3 * numEdge )
407  * @param numLocs       - (IN) number of locations to evaluate per edge
408  * @param paramLocation - (IN) parametric location to evaluate on each edge
409  *                             length = numLocs
410  * @param location      - (OUT) evaluated point on edge at paramLocation
411  *                              length = numEdge * 3 * numLocs
412  * @param tangent       - (IN/OUT) evaluated tangent at parmLocation. If NULL
413  *                              then will not be evaluated. Return vector
414  *                              is normalized
415  *                              length = numEdge * 3 * numLocs               
416  */
417 void evalBezierEdge( int numEdge, int numVert, int* edgeVert,
418                      double* vert, double* edgeCtrlPts,
419                      int numLocs, double* paramLocation,
420                      double* location, double* tangent );
421
422 /**
423  * Project to a quartic Bezier curve at a specified parametric location
424  * given its tangents at the end-points. Evaluates location,
425  * and/or tangent.  Finds only one point; in rare cases, more than one
426  * closest point might exist.
427  *
428  * @param numEdge       - (IN) number of edges on the faces
429  * @param numVert       - (IN) number of vertices
430  * @param edgeVert      - (IN) array of edge to vertex indecies (into vert)
431  *                             length 2 * numEdge
432  * @param vert          - (IN) array of vertex locations
433  *                              length = 3 * NumVerts
434  * @param edgeVertTang  - (IN) array of tangents at the edge vertices
435  *                              length 3*(2*numEdge)
436  * @param numLocs       - (IN) number of locations to evaluate per edge
437  * @param xyz           - (IN) xyz locations to project to each edge       
438  *                               length = 3 * numLocs                             
439  * @param xyzOnEdge     - (OUT) locations on edges closest to input points xyz.
440  *                              length = numEdge * 3 * numLocs
441  * @param tangent       - (IN/OUT) evaluated tangent at parmLocation. If NULL
442  *                              then will not be evaluated. Return vector
443  *                              is normalized
444  *                              length = numEdge * 3 * numLocs               
445  */
446 void projToBezierEdgeFromTans( int numEdge, int numVert, int* edgeVert,
447                               double* vert, double* edgeVertTang,
448                               int numLocs, double* xyz,
449                               double* xyzOnEdge, double* tangent );
450
451 /**
452  * Project a 3d point to a quartic Bezier curve at a specified parametric
453  * location given its control points.
454  *
455  * @param numEdge       - (IN) number of edges on the faces
456  * @param numVert       - (IN) number of vertices
457  * @param edgeVert      - (IN) array of edge to vertex indecies (into vert)
458  *                             length 2 * numEdge
459  * @param vert          - (IN) array of vertex locations
460  *                              length = 3 * numVert
461  * @param edgeCtrlPts   - (IN) array of control pt locations for each edge in
462  *                              the bezier.  The beziers are quartic, so there
463  *                              are 3 control pts per curve in addition to the
464  *                              2 end pts for each curve for a total of 5 pts
465  *                              per edge.
466  *                              length = 3 * ( 3 * numEdge )
467  * @param numLocs       - (IN) number of locations to evaluate per edge
468  * @param xyz           - (IN) xyz locations to evaluate on each edge       
469  *                               length = 3 * numLocs                             
470  * @param xyzOnEdge     - (OUT) locations on edges closest to input points xyz.
471  *                              length = numEdge * 3 * numLocs
472  * @param tangent       - (IN/OUT) evaluated tangent at parmLocation. If NULL
473  *                              then will not be evaluated. Return vector
474  *                              is normalized
475  *                              length = numEdge * 3 * numLocs
476  * @param t_value       - (OUT) value of the parameter at the projected point               
477  *                              length = numEdge * numLocs
478  */
479 void projToBezierEdge( int numEdge, int numVert, int* edgeVert,
480                        double* vert, double* edgeCtrlPts,
481                        int numLocs, double* xyz,
482                        double* xyzOnEdge, double* tangent, double* t_value );
483
484 /**
485  * Functions for debugging
486  **/
487
488 /*
489  *
490  *
491  *
492  *
493  */
494 /* dump the face mesh to a file that can be read by CUBIT
495  * Use the same definition of parameters as used with resolveFaceVectors
496  *
497  * @param fileName      - name of file to write to (will be overwritten)
498  * @param includeResults- if (0) then don't write face/edge vectors to file
499  */
500 void dumpMesh(const char *fileName, int includeResults, double angle,
501               int numTri, int numQuad, int numEdge,
502               int numVert, int* triEdge, int* quadEdge,
503               int* edgeVert, double* vert,
504               double* edgeCtrlPts, double* triCtrlPts,
505               double* quadCtrlPts);
506
507 /* dump only the results to a file
508  */
509 void dumpResults(const char *fileName, int numEdge, int numTri, int numQuad,
510                  double* edgeCtrlPts, double* triCtrlPts,
511                  double* quadCtrlPts );
512
513 /* import the face mesh from the specified file
514  * This is used by Cubit for debugging purposes
515  *
516  * @param fileName      - name of file to read from. 
517  *                        (file typically written by dumpMesh)
518  */
519 void importMesh(const char *fileName, int *resultsIncluded,
520                 double *angle, int *numTri, int *numQuad, int *numEdge,
521                 int *numVert, int** triEdge, int** quadEdge,
522                 int** edgeVert, double** vert,
523                 double** edgeCtrlPts, double** triCtrlPts,
524                 double** quadCtrlPts);
525
526 /* read only the results from a file
527  */
528 void importResults(const char *fileName, int *numEdge, int *numTri,
529                    int *numQuad, double** edgeCtrlPts, double** triCtrlPts,
530                    double** quadCtrlPts );
531
532
533 #endif
534
Note: See TracBrowser for help on using the browser.