File: track.h

package info (click to toggle)
yorick 2.2.03+dfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,620 kB
  • ctags: 9,317
  • sloc: ansic: 85,521; sh: 1,665; cpp: 1,282; lisp: 1,234; makefile: 1,034; fortran: 19
file content (202 lines) | stat: -rw-r--r-- 8,851 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 * $Id: track.h,v 1.1 2005-09-18 22:04:56 dhmunro Exp $
 * Routines for tracking a straight ray in 3D through a cylindrical mesh.
 */
/* Copyright (c) 2005, The Regents of the University of California.
 * All rights reserved.
 * This file is part of yorick (http://yorick.sourceforge.net).
 * Read the accompanying LICENSE file for details.
 */

#ifndef TRACK_H
#define TRACK_H
#include "bound.h"

/* ---------------------------------------------------------------------- */

/* The result of a ray tracking operation is a RayPath: */
typedef struct RayPath RayPath;
struct RayPath {
   long maxcuts, ncuts; /* physical lengths, current number zones cut */
   long *zone;          /* [ncuts] array of zone entered, if last exit
                         * (into region 0) then zone=0 */
   double *ds;          /* [ncuts] path length in zone (0.0 if zone=0) */
   long *pt1, *pt2;     /* [ncuts] arrays, pt1->pt2 is edge of zone cut */
   double *f;           /* [ncuts] cut at pt1 + (f+0.5)*(pt2-pt1) */
   double fi,ff;        /* fraction of distance into initial (final)
                         * zone at which tracking started (stopped)
                         * ds in initial (final) zone is 1-fi (1-ff) of
                         * the full length of the ray within the zone */
};

/* Although the mesh lives in a 2-D cylindrical coordinate space, a Ray
 * is a directed line in Cartesian 3-D space.  The z-axis is common to
 * the two coordinate systems.  The x-axis coincides with the r-axis
 * in a standard (z,r) mesh plot (although, of course, r>=0, while x
 * can have either sign).  The y-axis comes out of the page of the
 * standard mesh plot, toward your face.  Hence, (x,y,z) is a right
 * handed coordinate frame.
 *
 * A ray is assumed to lie in a plane of constant y.  The angle theta
 * is the angle from the +z direction to the ray direction, with
 * theta=+pi/2 corresponding to the +x-direction.  (This is opposite
 * the convention in TDG/DIRT, but corresponds to phi=0 azimuth in
 * the usual spherical coordinate system, e.g.- Jackson's E&M book.)
 *
 * The redundant data in the Ray structure allows the ray tracker to
 * step from edge to edge without having to compute a lot of extra
 * square roots, e.g.- to get r=sqrt(x^2+y^2) or sin=sqrt(1-cos^2).
 * (The alternative approach, used in TDG/DIRT, is to describe the ray
 * in an invariant fashion, i.e.- independent of the current zone in
 * the tracking process.)
 */
typedef struct Ray Ray;
struct Ray {
   double cos, sin;     /* cos(theta), sin(theta) */
   double y, z, x;      /* any point on the ray...
                         * y remains fixed,
                         * while z and x step from edge to edge */
   double r;            /* (z,r) are cylindrical coordinates corresponding
                         * to (x,y,z)   --   r^2 = x^2 + y^2 */
};

/* Structure to store results of a ray-edge intersection calculation
 * made by ExitEdge.  There are potentially two solutions, the "exit"
 * solution, representing a left-to-right crossing in (z,r) space, and
 * the "entry" solution, representing a right-to-left crossing.
 * Neither solution necessarily exists.  Several intermediate results
 * of the calculation are saved here, as well as the two roots.
 */
typedef struct RayEdgeInfo RayEdgeInfo;
struct RayEdgeInfo {
   double dz, dr;       /* edge vector in (z,r) plane */
   double area;         /* a useful cross product (see EdgeExit) */
   double A, B, C;      /* Af^2+Bf+C=0 is equation for fx, fn --
                         * neither B nor C valid unless D>0 */
   double D;            /* sqrt(discriminant) if >0, else discriminant */
   double fx;           /* the left-to-right crossing (edge fraction) */
   int validx;          /* fx not valid unless this is true */
   double fn;           /* the right-to-left crossing (edge fraction) */
   int validn;          /* fn not valid unless this is true */
};

/* A ray enters the mesh to begin tracking at one or more EntryPoint's: */
typedef struct EntryPoint EntryPoint;
struct EntryPoint {
   EntryPoint *next;
   Ray ray;
   RayEdgeInfo info;
   long zone;
   int side;
   double f;
   double s0;
};

/* ---------------------------------------------------------------------- */

/* Given the mesh boundary (i.e.- list of boundary edges) and a ray,
 * return a linked list of entry point(s), ordered by increasing time.
 */
extern EntryPoint *FindEntryPoints(Boundary *boundary, Ray *ray);

extern void FreeEntryPoints(EntryPoint *entry);

/* Starting at the given entry point(s), track the ray through the mesh.
 * The path arrays will be lengthened if necessary, but never shortened.
 * sLimits[0] <= s[1]<=s[ncuts-2] <= sLimits[1], if sLimits[0]<sLimits[1]
 * on entry.  (Note that s[0] and s[ncuts-1] may lie outside range.)
 */
extern void RayTrack(Mesh *mesh, EntryPoint *entry, RayPath *path,
                     double *sLimits);

/* Track the ray through the mesh, assuming it represents a sphere.
 * The path arrays will be lengthened if necessary, but never shortened.
 * sLimits[0] <= s[1]<=s[ncuts-2] <= sLimits[1], if sLimits[0]<sLimits[1]
 * on entry.  (Note that s[0] and s[ncuts-1] may lie outside range.)
 */
extern void RayTrackS(Mesh *mesh, Ray *ray, RayPath *path, double *sLimits);

/* Find the intersections of a ray with an edge (z,r); return true if
 * and only if the ray cuts the edge segment from left to right.
 */
extern int
ExitEdge(Ray *ray, double z[2], double r[2],    /* inputs */
         int *after, /* int *notafter, */       /* updates */
         RayEdgeInfo *info);                    /* output */

/* Compute the path length from the current point on the ray to the
 * exit (left-to-right) intersection computed by ExitEdge.
 */
extern double RayPathLength(Ray *ray, RayEdgeInfo *info);

/* Compute the path length from the exit point to the entry point (>0
 * if entry AFTER exit) for the intersections computed by ExitEdge.
 */
extern double RayPathDifference(RayEdgeInfo *info);

/* Given a ray with current point entering a particular zone and side of
 * the mesh, find the corresponding exit.  The path length ds is >=0
 * unless the ray segment lies in the negative area part of a bowtied
 * zone, in which case ds<0.  Return the exit side index (0<=side<=3).
 * Update the current point on the ray to the exit point.
 */
extern int
ExitZone(Mesh *mesh, long zone,         /* input mesh and zone number */
         int side,                      /* input side number on entry */
         Ray *ray,                      /* updated to exit point */
         RayEdgeInfo *info[4],          /* info[3] is entry side on entry,
                                         * updated to exit side on exit */
         double *ds,                    /* output ray path length */
         double *f);                    /* output edge fraction */

/* Although algebraically exact formulas are used for the ExitEdge
 * calculation, roundoff errors may make the redundant information
 * in the Ray structure (y,z,x, and r) inconsistent.  PolishExit
 * attempts to restore precise self-consistency of the ray, without
 * moving the point off of the current edge (remembered in info).
 */
extern void PolishExit(Ray *ray, RayEdgeInfo *info, double *ds, double *f);

/* Through roundoff errors, it is possible for the exit point found
 * in ExitZone (or FindEntryPoints) to lie slightly beyond the
 * endpoints of the exit edge.  AdjustRayXY moves the ray back to
 * the nearby endpoint when this occurs.
 */
extern void AdjustRayXY(Ray *ray, double* z, double *r);

/* Last ditch effort by ExitZone to find the exit edge */
extern int FindLostRay(Ray *ray, RayEdgeInfo *info[4],
                       double z[4], double r[4], double dsx[4]);

/* Rearrange the linked list of entry points into increasing order */
extern EntryPoint *EntrySort(EntryPoint *entry);

/* Make ray path arrays longer */
extern void ExtendRayPath(RayPath *path, long pathinc);

/* Free all pointers in a RayPath (but NOT the input path pointer).  */
extern void EraseRayPath(RayPath *path);

/* Adjust point on ray (x,y,z) and (z,r) to be point such that normal
 * plane to ray passes through origin.
 */
void NormalizeRay(Ray *ray);

/* ---------------------------------------------------------------------- */

/********** DEFAULT VALUES SET IN track.c ********/

/* Global variables control the root polishing routine PolishExit */
extern int polishRoot;
extern double polishTol1;
extern double polishTol2;

/* Global variable controlling roundoff tolerance in FindLostRay */
/* Setting this too large could result in an infinite loop, but in
 * any such situation, FindLostRay will be unable to find the ray
 * no matter what the setting of findRayTol */
extern double findRayTol;

/* ---------------------------------------------------------------------- */

#endif