ParticleAPI 3.0.0 Performant particle system API in C++ for interactive graphics

pDomain.h
Go to the documentation of this file.
1/// PDomain.h
2///
3/// Copyright 1997-2007, 2022 by David K. McAllister
4///
5/// This file defines the pDomain struct and all of the classes that derive from it.
6
7#ifndef pdomain_h
8#define pdomain_h
9
10#include "Particle/pDeclarations.h"
11#include "Particle/pError.h"
12#include "Particle/pVec.h"
13
14#include <string>
15#include <vector>
16
17namespace PAPI {
18///< How small the dot product must be to declare that a point is in a plane for Within().
19#define P_PLANAR_EPSILON 1e-3f
20
21/// Enums for the different types of domains that can be stored in a pDomain
22 enum pDomainType_E {
23 PDUnion_e,
24 PDPoint_e,
25 PDLine_e,
26 PDTriangle_e,
27 PDRectangle_e,
28 PDDisc_e,
29 PDPlane_e,
30 PDBox_e,
31 PDCylinder_e,
32 PDCone_e,
33 PDSphere_e,
34 PDBlob_e,
35};
36
37/// A representation of a region of space.
38///
39/// A Domain is a representation of a region of space. For example, the Source action uses a domain to describe the volume in which a particle
40/// will be created. A random point within the domain is chosen as the initial position of the particle. The Avoid, Sink and Bounce actions,
41/// for example, use domains to describe a volume in space for particles to steer around, die when they enter, or bounce off, respectively.
42///
43/// Domains can be used to describe velocities. Picture the velocity vector as having its tail at the origin and its tip being in the domain.
44/// Domains can be used to describe colors in any three-valued color space. They can be used to describe three-valued sizes, such as Length, Width, Height.
45///
46/// Several types of domains can be specified, such as points, lines, planes, discs, spheres, gaussian blobs, etc. Each subclass of the pDomain
47/// struct represents a different kind of domain.
48///
49/// All domains support two basic operations. The first is Generate, which returns a random point in the domain.
50///
51/// The second basic operation is Within, which tells whether a given point is within the domain.
52///
53/// The application programmer never calls the Generate or Within functions. The application will use the pDomain struct and its derivatives solely
54/// as a way to communicate the domain to the API. The API's action commands will then perform operations on the domain, such as generating particles within it.
55 class pDomain {
56public:
57#define P_N_FLOATS_IN_DOMAIN 30
58 pDomainType_E Which;
59 virtual bool Within(const pVec&) const = 0; ///< Returns true if the given point is within the domain.
60 virtual pVec Generate() const = 0; ///< Returns a random point in the domain.
61 virtual float Size() const = 0; ///< Returns the size of the domain (length, area, or volume).
62
63 virtual std::shared_ptr<pDomain> copy() const = 0; // Returns a pointer to a heap-allocated copy of the derived class
64};
65
66namespace {
67// Compute the inverse matrix of the plane basis.
68 PINLINE void NewBasis(const pVec& u, const pVec& v, pVec& s1, pVec& s2)
69{
70 pVec w = Cross(u, v);
71
72 float det = 1.0f /
73 (w.z() * u.x() * v.y() - w.z() * u.y() * v.x() - u.z() * w.x() * v.y() - u.x() * v.z() * w.y() + v.z() * w.x() * u.y() + u.z() * v.x() * w.y());
74
75 s1 = pVec((v.y() * w.z() - v.z() * w.y()), (v.z() * w.x() - v.x() * w.z()), (v.x() * w.y() - v.y() * w.x()));
76 s1 *= det;
77 s2 = pVec((u.y() * w.z() - u.z() * w.y()), (u.z() * w.x() - u.x() * w.z()), (u.x() * w.y() - u.y() * w.x()));
78 s2 *= -det;
79}
80}; // namespace
81
82/// A CSG union of multiple domains.
83///
84/// A point is within this domain if it is within any subdomain.
85/// Generate returns a point from any subdomain.
86/// Within returns true if pos is within any subdomain.
87///
88/// All domains have a Size() that is used to apportion probability between the domains in the union.
89/// Sizes of domains of the same dimensionality are commensurate but sizes of differing dimensionality are not.
90/// Thus, to properly distribute probability of Generate() choosing each domain, it is wise to only combine domains that have the same
91/// dimensionality. Note that thin shelled cylinders, cones, and spheres, where InnerRadius==OuterRadius, are considered 2D, not 3D.
92/// Thin shelled discs (circles) are considered 1D. Points are 0D.
93 struct PDUnion : public pDomain {
94 std::vector<std::shared_ptr<pDomain>> Doms;
95 float TotalSize;
96
97 PDUnion() /// Use this one to create an empty PDUnion then call .insert() to add each item to it.
98 {
99 Which = PDUnion_e;
100 TotalSize = 0.0f;
101 }
102
103 PDUnion(const pDomain& A, const pDomain& B)
104 {
105 Which = PDUnion_e;
106 TotalSize = A.Size() + B.Size();
107 Doms.push_back(A.copy());
108 Doms.push_back(B.copy());
109 }
110
111 PDUnion(const pDomain& A, const pDomain& B, const pDomain& C)
112 {
113 Which = PDUnion_e;
114 TotalSize = A.Size() + B.Size() + C.Size();
115 Doms.push_back(A.copy());
116 Doms.push_back(B.copy());
117 Doms.push_back(C.copy());
118 }
119
120 /// Makes a copy of all the subdomains and point to the copies.
121 ///
122 /// Note that the Generate() function goes faster if you supply DomList with the largest domains first.
123 PDUnion(const std::vector<std::shared_ptr<pDomain>>& DomList)
124 {
125 Which = PDUnion_e;
126 TotalSize = 0.0f;
127 for (std::vector<std::shared_ptr<pDomain>>::const_iterator it = DomList.begin(); it != DomList.end(); it++) {
128 Doms.push_back((*it)->copy());
129 TotalSize += (*it)->Size();
130 }
131 }
132
133 /// Makes a copy of all the subdomains and point to the copies.
134 PDUnion(const PDUnion& P)
135 {
136 Which = PDUnion_e;
137 TotalSize = 0.0f;
138 for (std::vector<std::shared_ptr<pDomain>>::const_iterator it = P.Doms.begin(); it != P.Doms.end(); it++) {
139 Doms.push_back((*it)->copy());
140 TotalSize += (*it)->Size();
141 }
142 }
143
144 /// Insert another domain into this PDUnion.
145 void insert(const pDomain& A)
146 {
147 TotalSize += A.Size();
148 Doms.push_back(A.copy());
149 }
150
151 bool Within(const pVec& pos) const /// Returns true if pos is within any of the domains.
152 {
153 for (std::vector<std::shared_ptr<pDomain>>::const_iterator it = Doms.begin(); it != Doms.end(); it++)
154 if ((*it)->Within(pos)) return true;
155 return false;
156 }
157
158 pVec Generate() const /// Generate a point in any subdomain, chosen by the ratio of their sizes.
159 {
160 float Choose = pRandf() * TotalSize, PastProb = 0.0f;
161 for (std::vector<std::shared_ptr<pDomain>>::const_iterator it = Doms.begin(); it != Doms.end(); it++) {
162 PastProb += (*it)->Size();
163 if (Choose <= PastProb) return (*it)->Generate();
164 }
165 throw PErrInternalError("Sizes didn't add up to TotalSize in PDUnion::Generate().");
166 }
167
168 float Size() const { return TotalSize; }
169
170 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDUnion(*this)); }
171};
172
173/// A single point.
174///
175/// Generate always returns this point. Within returns true if the point is exactly equal.
176 struct PDPoint : public pDomain {
177 pVec p;
178
179 PINLINE PDPoint(const pVec& p0)
180 {
181 Which = PDPoint_e;
182 PDPoint_Cons(p0);
183 }
184
185 PINLINE void PDPoint_Cons(const pVec& p0) { p = p0; }
186
187 PINLINE bool Within(const pVec& pos) const /// Returns true if the point is exactly equal.
188 {
189 return p == pos;
190 }
191
192 PINLINE pVec Generate() const /// Returns the point
193 {
194 return p;
195 }
196
197 PINLINE float Size() const { return 1.0f; }
198
199 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDPoint(*this)); }
200};
201
202/// A line segment.
203///
204/// e0 and e1 are the endpoints of the segment.
205///
206/// Generate returns a random point on this segment. Within returns true for points within epsilon of the line segment.
207 struct PDLine : public pDomain {
208 pVec p0, p1, vec, vecNrm;
209 float len;
210
211 PINLINE PDLine(const pVec& e0, const pVec& e1)
212 {
213 Which = PDLine_e;
214 PDLine_Cons(e0, e1);
215 }
216
217 PINLINE void PDLine_Cons(const pVec& e0, const pVec& e1)
218 {
219 p0 = e0;
220 p1 = e1;
221 vec = e1 - e0;
222 vecNrm = vec;
223 vecNrm.normalize();
224 len = vec.length();
225 }
226
227 PINLINE bool Within(const pVec& pos) const /// Returns true for points within epsilon of the line segment.
228 {
229 pVec to = pos - p0;
230 float d = dot(vecNrm, to);
231 float dif = fabs(d - to.length()) / len; // Has a sqrt(). Kind of slow.
232 return dif < 1e-7f; // It's inaccurate, so we need this epsilon.
233 }
234
235 PINLINE pVec Generate() const /// Returns a random point on this segment.
236 {
237 return p0 + vec * pRandf();
238 }
239
240 PINLINE float Size() const { return len; }
241
242 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDLine(*this)); }
243};
244
245/// A Triangle.
246///
247/// p0, p1, and p2 are the vertices of the triangle. The triangle can be used to define an arbitrary geometrical model for particles to
248/// bounce off, or generate particles on its surface (and explode them), etc.
249///
250/// Generate returns a random point in the triangle. Within returns true for points within epsilon of the triangle. Currently it is not
251/// possible to sink particles that enter/exit a polygonal model. Suggestions?
252 struct PDTriangle : public pDomain {
253 pVec p, u, v, uNrm, vNrm, nrm, s1, s2;
254 float uLen, vLen, D, area;
255
256 PINLINE PDTriangle(const pVec& p0, const pVec& p1, const pVec& p2)
257 {
258 Which = PDTriangle_e;
259 PDTriangle_Cons(p0, p1, p2);
260 }
261
262 PINLINE void PDTriangle_Cons(const pVec& p0, const pVec& p1, const pVec& p2)
263 {
264 p = p0;
265 u = p1 - p0;
266 v = p2 - p0;
267
268 uLen = u.length();
269 uNrm = u / uLen;
270 vLen = v.length();
271 vNrm = v / vLen;
272
273 nrm = Cross(uNrm, vNrm); // This is the non-unit normal.
274 nrm.normalize(); // Must normalize it.
275
276 D = -dot(p, nrm);
277
278 NewBasis(u, v, s1, s2); // Compute the inverse matrix of the plane basis.
279
280 // Compute the area
281 pVec Hgt = v - uNrm * dot(uNrm, v);
282 float h = Hgt.length();
283 area = 0.5f * uLen * h;
284 }
285
286 PINLINE bool Within(const pVec& pos) const /// Returns true for points within epsilon of the triangle.
287 {
288 pVec offset = pos - p;
289 float d = dot(offset, nrm);
290
291 if (d > P_PLANAR_EPSILON) return false;
292
293 // Dot product with basis vectors of old frame
294 // in terms of new frame gives position in uv frame.
295 float upos = dot(offset, s1);
296 float vpos = dot(offset, s2);
297
298 // Did it cross plane outside triangle?
299 return !(upos < 0 || vpos < 0 || (upos + vpos) > 1);
300 }
301
302 PINLINE pVec Generate() const /// Returns a random point in the triangle.
303 {
304 float r1 = pRandf();
305 float r2 = pRandf();
306 pVec pos;
307 if (r1 + r2 < 1.0f)
308 pos = p + u * r1 + v * r2;
309 else
310 pos = p + u * (1.0f - r1) + v * (1.0f - r2);
311
312 return pos;
313 }
314
315 PINLINE float Size() const { return area; }
316
317 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDTriangle(*this)); }
318};
319
320/// Rhombus-shaped planar region.
321///
322/// p0 is a point on the plane. u0 and v0 are (non-parallel) basis vectors in the plane. They don't need to be normal or orthogonal.
323///
324/// Generate returns a random point in the diamond-shaped patch whose corners are o, o+u, o+u+v, and o+v. Within returns true for points within epsilon of the patch.
325 struct PDRectangle : public pDomain {
326 pVec p, u, v, uNrm, vNrm, nrm, s1, s2;
327 float uLen, vLen, D, area;
328
329 PINLINE PDRectangle(const pVec& p0, const pVec& u0, const pVec& v0)
330 {
331 Which = PDRectangle_e;
332 PDRectangle_Cons(p0, u0, v0);
333 }
334
335 PINLINE void PDRectangle_Cons(const pVec& p0, const pVec& u0, const pVec& v0)
336 {
337 p = p0;
338 u = u0;
339 v = v0;
340
341 uLen = u.length();
342 uNrm = u / uLen;
343 vLen = v.length();
344 vNrm = v / vLen;
345
346 nrm = Cross(uNrm, vNrm); // This is the non-unit normal.
347 nrm.normalize(); // Must normalize it.
348
349 D = -dot(p, nrm);
350
351 NewBasis(u, v, s1, s2); // Compute the inverse matrix of the plane basis.
352
353 // Compute the area
354 pVec Hgt = v - uNrm * dot(uNrm, v);
355 float h = Hgt.length();
356 area = uLen * h;
357 }
358
359 PINLINE bool Within(const pVec& pos) const /// Returns true for points within epsilon of the patch.
360 {
361 pVec offset = pos - p;
362 float d = dot(offset, nrm);
363
364 if (d > P_PLANAR_EPSILON) return false;
365
366 // Dot product with basis vectors of old frame
367 // in terms of new frame gives position in uv frame.
368 float upos = dot(offset, s1);
369 float vpos = dot(offset, s2);
370
371 // Did it cross plane outside triangle?
372 return !(upos < 0 || upos > 1 || vpos < 0 || vpos > 1);
373 }
374
375 PINLINE pVec Generate() const /// Returns a random point in the diamond-shaped patch whose corners are o, o+u, o+u+v, and o+v.
376 {
377 pVec pos = p + u * pRandf() + v * pRandf();
378 return pos;
379 }
380
381 PINLINE float Size() const { return area; }
382
383 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDRectangle(*this)); }
384};
385
386/// Arbitrarily-oriented disc
387///
388/// The point Center is the center of a disc in the plane with normal Normal. The disc has an OuterRadius. If InnerRadius is greater than 0,
389/// the domain is a flat washer, rather than a disc. The normal will get normalized, so it need not already be unit length.
390///
391/// Generate returns a point inside the disc shell. Within returns true for points within epsilon of the disc.
392 struct PDDisc : public pDomain {
393 pVec p, nrm, u, v;
394 float radIn, radOut, radInSqr, radOutSqr, dif, D, area;
395
396 PINLINE PDDisc(const pVec& Center, const pVec Normal, const float OuterRadius, const float InnerRadius = 0.0f)
397 {
398 if (InnerRadius < 0 || OuterRadius < 0) throw PErrInvalidValue("Can't have negative radius.");
399
400 Which = PDDisc_e;
401 PDDisc_Cons(Center, Normal, OuterRadius, InnerRadius);
402 }
403
404 PINLINE void PDDisc_Cons(const pVec& Center, const pVec Normal, const float OuterRadius, const float InnerRadius = 0.0f)
405 {
406 p = Center;
407 nrm = Normal;
408 nrm.normalize();
409
410 if (OuterRadius > InnerRadius) {
411 radOut = OuterRadius;
412 radIn = InnerRadius;
413 } else {
414 radOut = InnerRadius;
415 radIn = OuterRadius;
416 }
417
418 radInSqr = fsqr(radIn);
419 radOutSqr = fsqr(radOut);
420 dif = radOut - radIn;
421
422 // Find a vector orthogonal to n.
423 pVec basis = pVec(1.0f, 0.0f, 0.0f);
424 if (fabsf(dot(basis, nrm)) > 0.999f) basis = pVec(0.0f, 1.0f, 0.0f);
425
426 // Project away N component, normalize and cross to get
427 // second orthonormal vector.
428 u = basis - nrm * dot(basis, nrm);
429 u.normalize();
430 v = Cross(nrm, u);
431 D = -dot(p, nrm);
432
433 if (dif == 0.0f)
434 area = 2.0f * M_PI * radOut; // Length of circle
435 else
436 area = M_PI * radOutSqr - M_PI * radInSqr; // Area or disc minus hole
437 }
438
439 PINLINE bool Within(const pVec& pos) const /// Returns true for points within epsilon of the disc.
440 {
441 pVec offset = pos - p;
442 float d = dot(offset, nrm);
443
444 if (d > P_PLANAR_EPSILON) return false;
445
446 float len = offset.lenSqr();
447 return len >= radInSqr && len <= radOutSqr;
448 }
449
450 PINLINE pVec Generate() const /// Returns a point inside the disc shell.
451 {
452 // Might be faster to generate a point in a square and reject if outside the circle
453 float theta = pRandf() * 2.0f * float(M_PI); // Angle around normal
454 // Distance from center
455 float r = radIn + pRandf() * dif;
456
457 float x = r * cosf(theta); // Weighting of each frame vector
458 float y = r * sinf(theta);
459
460 pVec pos = p + u * x + v * y;
461 return pos;
462 }
463
464 PINLINE float Size() const
465 {
466 return 1.0f; // A plane is infinite, so what sensible thing can I return?
467 }
468
469 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDDisc(*this)); }
470};
471
472/// Arbitrarily-oriented plane.
473///
474/// The point p0 is a point on the plane. Normal is the normal vector of the plane. If you have a plane in a,b,c,d form remember that
475/// n = [a,b,c] and you can compute a suitable point p0 as p0 = -n*d. The normal will get normalized, so it need not already be unit length.
476///
477/// Generate returns the point p0. Within returns true if the point is in the positive half-space of the plane (in the plane or on the side that Normal points to).
478 struct PDPlane : public pDomain {
479 pVec p, nrm;
480 float D;
481
482 PINLINE PDPlane(const pVec& p0, const pVec& Normal)
483 {
484 Which = PDPlane_e;
485 PDPlane_Cons(p0, Normal);
486 }
487
488 PINLINE void PDPlane_Cons(const pVec& p0, const pVec& Normal)
489 {
490 p = p0;
491 nrm = Normal;
492 nrm.normalize(); // Must normalize it.
493 D = -dot(p, nrm);
494 }
495
496 // Distance from plane = n * p + d
497 // Inside is the positive half-space.
498 PINLINE bool
499 Within(const pVec& pos) const /// Returns true if the point is in the positive half-space of the plane (in the plane or on the side that Normal points to).
500 {
501 return dot(nrm, pos) >= -D;
502 }
503
504 // How do I sensibly make a point on an infinite plane?
505 PINLINE pVec Generate() const /// Returns the point p0.
506 {
507 return p;
508 }
509
510 PINLINE float Size() const
511 {
512 return 1.0f; // A plane is infinite, so what sensible thing can I return?
513 }
514
515 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDPlane(*this)); }
516};
517
518/// Axis-aligned bounding box (AABB)
519///
520/// e0 and e1 are opposite corners of an axis-aligned box. It doesn't matter which of each coordinate is min and which is max.
521///
522/// Generate returns a random point in this box. Within returns true if the point is in the box.
523 struct PDBox : public pDomain {
524 // P0 is the min corner. p1 is the max corner.
525 pVec p0, p1, dif;
526 float vol;
527
528 PINLINE PDBox(const pVec& e0, const pVec& e1)
529 {
530 Which = PDBox_e;
531 PDBox_Cons(e0, e1);
532 }
533
534 PINLINE void PDBox_Cons(const pVec& e0, const pVec& e1)
535 {
536 p0 = e0;
537 p1 = e1;
538 if (e1.x() < e0.x()) {
539 p0.x() = e1.x();
540 p1.x() = e0.x();
541 }
542 if (e1.y() < e0.y()) {
543 p0.y() = e1.y();
544 p1.y() = e0.y();
545 }
546 if (e1.z() < e0.z()) {
547 p0.z() = e1.z();
548 p1.z() = e0.z();
549 }
550
551 dif = p1 - p0;
552 vol = dif.x() * dif.y() * dif.z();
553 }
554
555 PINLINE bool Within(const pVec& pos) const /// Returns true if the point is in the box.
556 {
557 return !((pos.x() < p0.x()) || (pos.x() > p1.x()) || (pos.y() < p0.y()) || (pos.y() > p1.y()) || (pos.z() < p0.z()) || (pos.z() > p1.z()));
558 }
559
560 PINLINE pVec Generate() const /// Returns a random point in this box.
561 {
562 // Scale and translate [0,1] random to fit box
563 return p0 + CompMult(pRandVec(), dif);
564 }
565
566 PINLINE float Size() const { return vol; }
567
568 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDBox(*this)); }
569};
570
571/// Cylinder
572///
573/// e0 and e1 are the endpoints of the axis of the right cylinder. OuterRadius is the outer radius, and InnerRadius is the inner
574/// radius for a cylindrical shell. InnerRadius = 0 for a solid cylinder with no empty space in the middle.
575///
576/// Generate returns a random point in the cylindrical shell. Within returns true if the point is within the cylindrical shell.
577 struct PDCylinder : public pDomain {
578 pVec apex, axis, u, v; // Apex is one end. Axis is vector from one end to the other.
579 float radIn, radOut, radInSqr, radOutSqr, radDif, axisLenInvSqr, vol;
580 bool ThinShell;
581
582 PINLINE PDCylinder(const pVec& e0, const pVec& e1, const float OuterRadius, const float InnerRadius = 0.0f)
583 {
584 if (InnerRadius < 0 || OuterRadius < 0) throw PErrInvalidValue("Can't have negative radius.");
585
586 Which = PDCylinder_e;
587 PDCylinder_Cons(e0, e1, OuterRadius, InnerRadius);
588 }
589
590 PINLINE void PDCylinder_Cons(const pVec& e0, const pVec& e1, const float OuterRadius, const float InnerRadius = 0.0f)
591 {
592 apex = e0;
593 axis = e1 - e0;
594
595 if (OuterRadius < InnerRadius) {
596 radOut = InnerRadius;
597 radIn = OuterRadius;
598 } else {
599 radOut = OuterRadius;
600 radIn = InnerRadius;
601 }
602
603 radOutSqr = fsqr(radOut);
604 radInSqr = fsqr(radIn);
605
606 ThinShell = (radIn == radOut);
607 radDif = radOut - radIn;
608
609 // Given an arbitrary nonzero vector n, make two orthonormal
610 // vectors u and v forming a frame [u,v,n.normalize()].
611 pVec n = axis;
612 float axisLenSqr = axis.lenSqr();
613 float len = sqrtf(axisLenSqr);
614 axisLenInvSqr = axisLenSqr ? (1.0f / axisLenSqr) : 0.0f;
615 n *= sqrtf(axisLenInvSqr);
616
617 // Find a vector orthogonal to n.
618 pVec basis = pVec(1.0f, 0.0f, 0.0f);
619 if (fabsf(dot(basis, n)) > 0.999f) basis = pVec(0.0f, 1.0f, 0.0f);
620
621 // Project away N component, normalize and cross to get
622 // second orthonormal vector.
623 u = basis - n * dot(basis, n);
624 u.normalize();
625 v = Cross(n, u);
626
627 float EndCapArea = M_PI * radOutSqr - M_PI * radInSqr;
628 if (ThinShell)
629 vol = len * 2.0f * M_PI * radOut; // Surface area of cylinder
630 else
631 vol = EndCapArea * len; // Volume of cylindrical shell
632 }
633
634 PINLINE bool Within(const pVec& pos) const /// Returns true if the point is within the cylindrical shell.
635 {
636 // This is painful and slow. Might be better to do quick accept/reject tests.
637 // Axis is vector from base to tip of the cylinder.
638 // x is vector from base to pos.
639 // x . axis
640 // dist = ---------- = projected distance of x along the axis
641 // axis. axis ranging from 0 (base) to 1 (tip)
642 //
643 // rad = x - dist * axis = projected vector of x along the base
644
645 pVec x = pos - apex;
646
647 // Check axial distance
648 float dist = dot(axis, x) * axisLenInvSqr;
649 if (dist < 0.0f || dist > 1.0f) return false;
650
651 // Check radial distance
652 pVec xrad = x - axis * dist; // Radial component of x
653 float rSqr = xrad.lenSqr();
654
655 return (rSqr >= radInSqr && rSqr <= radOutSqr);
656 }
657
658 PINLINE pVec Generate() const /// Returns a random point in the cylindrical shell.
659 {
660 float dist = pRandf(); // Distance between base and tip
661 float theta = pRandf() * 2.0f * float(M_PI); // Angle around axis
662 // Distance from axis
663 float r = radIn + pRandf() * radDif;
664
665 // Another way to do this is to choose a random point in a square and keep it if it's in the circle.
666 float x = r * cosf(theta);
667 float y = r * sinf(theta);
668
669 pVec pos = apex + axis * dist + u * x + v * y;
670 return pos;
671 }
672
673 PINLINE float Size() const /// Returns the thick cylindrical shell volume or the thin cylindrical shell area if OuterRadius==InnerRadius.
674 {
675 return vol;
676 }
677
678 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDCylinder(*this)); }
679};
680
681/// Cone
682///
683/// e0 is the apex of the cone and e1 is the endpoint of the axis at the cone's base. OuterRadius is the radius of the base of the cone.
684/// InnerRadius is the radius of the base of a cone to subtract from the first cone to create a conical shell. This is similar to the
685/// cylindrical shell, which can be thought of as a large cylinder with a smaller cylinder subtracted from the middle. Both cones share the
686/// same apex and axis, which implies that the thickness of the conical shell tapers to 0 at the apex. InnerRadius = 0 for a solid cone with
687/// no empty space in the middle.
688///
689/// Generate returns a random point in the conical shell. Within returns true if the point is within the conical shell.
690 struct PDCone : public pDomain {
691 pVec apex, axis, u, v; // Apex is one end. Axis is vector from one end to the other.
692 float radIn, radOut, radInSqr, radOutSqr, radDif, axisLenInvSqr, vol;
693 bool ThinShell;
694
695 PINLINE PDCone(const pVec& e0, const pVec& e1, const float OuterRadius, const float InnerRadius = 0.0f)
696 {
697 if (InnerRadius < 0 || OuterRadius < 0) throw PErrInvalidValue("Can't have negative radius.");
698
699 Which = PDCone_e;
700 PDCone_Cons(e0, e1, OuterRadius, InnerRadius);
701 }
702
703 PINLINE void PDCone_Cons(const pVec& e0, const pVec& e1, const float OuterRadius, const float InnerRadius = 0.0f)
704 {
705 apex = e0;
706 axis = e1 - e0;
707
708 if (OuterRadius < InnerRadius) {
709 radOut = InnerRadius;
710 radIn = OuterRadius;
711 } else {
712 radOut = OuterRadius;
713 radIn = InnerRadius;
714 }
715
716 radOutSqr = fsqr(radOut);
717 radInSqr = fsqr(radIn);
718
719 ThinShell = (radIn == radOut);
720 radDif = radOut - radIn;
721
722 // Given an arbitrary nonzero vector n, make two orthonormal
723 // vectors u and v forming a frame [u,v,n.normalize()].
724 pVec n = axis;
725 float axisLenSqr = axis.lenSqr();
726 float len = sqrtf(axisLenSqr);
727 axisLenInvSqr = axisLenSqr ? 1.0f / axisLenSqr : 0.0f;
728 n *= sqrtf(axisLenInvSqr);
729
730 // Find a vector orthogonal to n.
731 pVec basis = pVec(1.0f, 0.0f, 0.0f);
732 if (fabsf(dot(basis, n)) > 0.999f) basis = pVec(0.0f, 1.0f, 0.0f);
733
734 // Project away N component, normalize and cross to get
735 // second orthonormal vector.
736 u = basis - n * dot(basis, n);
737 u.normalize();
738 v = Cross(n, u);
739
740 if (ThinShell)
741 vol = sqrtf(axisLenSqr + radOutSqr) * M_PI * radOut; // Surface area of cone (not counting endcap)
742 else {
743 float OuterVol = 0.33333333f * M_PI * radOutSqr * len;
744 float InnerVol = 0.33333333f * M_PI * radInSqr * len;
745 vol = OuterVol - InnerVol; // Volume of conical shell
746 }
747 }
748
749 PINLINE bool Within(const pVec& pos) const /// Returns true if the point is within the conical shell.
750 {
751 // This is painful and slow. Might be better to do quick
752 // accept/reject tests.
753 // Let axis = vector from base to tip of the cone
754 // x = vector from base to test point
755 // x . axis
756 // dist = ---------- = projected distance of x along the axis
757 // axis. axis ranging from 0 (base) to 1 (tip)
758 //
759 // rad = x - dist * axis = projected vector of x along the base
760
761 pVec x = pos - apex;
762
763 // Check axial distance
764 // axisLenInvSqr stores 1 / dot(axis, axis)
765 float dist = dot(axis, x) * axisLenInvSqr;
766 if (dist < 0.0f || dist > 1.0f) return false;
767
768 // Check radial distance; scale radius along axis for cones
769 pVec xrad = x - axis * dist; // Radial component of x
770 float rSqr = xrad.lenSqr();
771
772 return (rSqr >= fsqr(dist * radIn) && rSqr <= fsqr(dist * radOut));
773 }
774
775 PINLINE pVec Generate() const /// Returns a random point in the conical shell.
776 {
777 float dist = pRandf(); // Distance between base and tip
778 float theta = pRandf() * 2.0f * float(M_PI); // Angle around axis
779 // Distance from axis
780 float r = radIn + pRandf() * radDif;
781
782 // Another way to do this is to choose a random point in a square and keep it if it's in the circle.
783 float x = r * cosf(theta);
784 float y = r * sinf(theta);
785
786 // Scale radius along axis for cones
787 x *= dist;
788 y *= dist;
789
790 pVec pos = apex + axis * dist + u * x + v * y;
791 return pos;
792 }
793
794 PINLINE float Size() const /// Returns the thick conical shell volume or the thin conical shell area if OuterRadius==InnerRadius.
795 {
796 return vol;
797 }
798
799 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDCone(*this)); }
800};
801
802/// Sphere
803///
804/// The point Center is the center of the sphere. OuterRadius is the outer radius of the spherical shell and InnerRadius is the inner radius.
805///
806/// Generate returns a random point in the thick shell at a distance between OuterRadius and InnerRadius from point Center. If InnerRadius
807/// is 0, then it is the whole sphere. Within returns true if the point lies within the thick shell at a distance between InnerRadius to OuterRadius from point Center.
808 struct PDSphere : public pDomain {
809 pVec ctr;
810 float radIn, radOut, radInSqr, radOutSqr, radDif, vol;
811 bool ThinShell;
812
813 PINLINE PDSphere(const pVec& Center, const float OuterRadius, const float InnerRadius = 0.0f)
814 {
815 if (InnerRadius < 0 || OuterRadius < 0) throw PErrInvalidValue("Can't have negative radius.");
816
817 Which = PDSphere_e;
818 PDSphere_Cons(Center, OuterRadius, InnerRadius);
819 }
820
821 PINLINE void PDSphere_Cons(const pVec& Center, const float OuterRadius, const float InnerRadius = 0.0f)
822 {
823 ctr = Center;
824
825 if (OuterRadius < InnerRadius) {
826 radOut = InnerRadius;
827 radIn = OuterRadius;
828 } else {
829 radOut = OuterRadius;
830 radIn = InnerRadius;
831 }
832
833 radOutSqr = fsqr(radOut);
834 radInSqr = fsqr(radIn);
835
836 ThinShell = (radIn == radOut);
837 radDif = radOut - radIn;
838
839 if (ThinShell)
840 vol = 4.0f * M_PI * radOutSqr; // Surface area of sphere
841 else {
842 float OuterVol = 1.33333333f * M_PI * radOutSqr * radOut;
843 float InnerVol = 1.33333333f * M_PI * radInSqr * radIn;
844 vol = OuterVol - InnerVol; // Volume of spherical shell
845 }
846 }
847
848 PINLINE bool Within(const pVec& pos) const /// Returns true if the point lies within the thick shell.
849 {
850 pVec rvec(pos - ctr);
851 float rSqr = rvec.lenSqr();
852 return rSqr <= radOutSqr && rSqr >= radInSqr;
853 }
854
855 PINLINE pVec Generate() const /// Returns a random point in the thick spherical shell.
856 {
857 pVec pos;
858
859 do {
860 pos = pRandVec() - pVec(0.5f, 0.5f, 0.5f); // Point on [-0.5,0.5] box
861 } while (pos.lenSqr() > fsqr(0.5)); // Make sure it's also on r=0.5 sphere.
862 pos.normalize(); // Now it's on r=1 spherical shell
863
864 // Scale unit sphere pos by [0..r] and translate
865 if (ThinShell) // I can't remember why I make this distinction. Is it for precision or speed? Speed doesn't seem likely.
866 pos = ctr + pos * radOut;
867 else
868 pos = ctr + pos * (radIn + pRandf() * radDif);
869
870 return pos;
871 }
872
873 PINLINE float Size() const /// Returns the thick spherical shell volume or the thin spherical shell area if OuterRadius==InnerRadius.
874 {
875 return vol;
876 }
877
878 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDSphere(*this)); }
879};
880
881/// Gaussian blob
882///
883/// The point Center is the center of a normal probability density of standard deviation StandardDev. The density is radially symmetrical.
884/// The blob domain allows for some very natural-looking effects because there is no sharp, artificial-looking boundary at the edge of the domain.
885///
886/// Generate returns a point with normal probability density. Within has a probability of returning true equal to the probability density at the specified point.
887 struct PDBlob : public pDomain {
888 pVec ctr;
889 float stdev, Scale1, Scale2;
890
891 PINLINE PDBlob(const pVec& Center, const float StandardDev)
892 {
893 Which = PDBlob_e;
894 PDBlob_Cons(Center, StandardDev);
895 }
896
897 PINLINE void PDBlob_Cons(const pVec& Center, const float StandardDev)
898 {
899 ctr = Center;
900 stdev = StandardDev;
901 float oneOverSigma = 1.0f / (stdev + 0.000000000001f);
902 Scale1 = -0.5f * fsqr(oneOverSigma);
903 Scale2 = P_ONEOVERSQRT2PI * oneOverSigma;
904 }
905
906 PINLINE bool Within(const pVec& pos) const /// Has a probability of returning true equal to the probability density at the specified point.
907 {
908 pVec x = pos - ctr;
909 float Gx = expf(x.lenSqr() * Scale1) * Scale2;
910 return (pRandf() < Gx);
911 }
912
913 PINLINE pVec Generate() const /// Returns a point with normal probability density.
914 {
915 return ctr + pNRandVec(stdev);
916 }
917
918 PINLINE float Size() const /// Returns the probability density integral, which is 1.0.
919 {
920 return 1.0f;
921 }
922
923 std::shared_ptr<pDomain> copy() const { return std::shared_ptr<pDomain>(new PDBlob(*this)); }
924};
925}; // namespace PAPI
926
927#endif
PAPI::pDomain
A representation of a region of space.
Definition: pDomain.h:55
PAPI::pDomain::Size
virtual float Size() const =0
Returns the size of the domain (length, area, or volume).
PAPI::pDomain::Generate
virtual pVec Generate() const =0
Returns a random point in the domain.
PAPI::pDomain::Which
pDomainType_E Which
Definition: pDomain.h:58
PAPI::pDomain::Within
virtual bool Within(const pVec &) const =0
Returns true if the given point is within the domain.
PAPI::pDomain::copy
virtual std::shared_ptr< pDomain > copy() const =0
PAPI::pVec
A single-precision floating point three-vector.
Definition: pVec.h:63
PAPI::pVec::CompMult
friend pVec CompMult(const pVec &a, const pVec &b)
Definition: pVec.h:159
PAPI::pVec::normalize
float normalize(const float toLen=1.f)
Definition: pVec.h:84
PAPI::pVec::pVec
pVec(float ax, float ay, float az)
Definition: pVec.h:67
PAPI::pVec::operator+
pVec operator+(const pVec &a) const
Definition: pVec.h:106
PAPI::pVec::operator*
pVec operator*(const float s) const
Definition: pVec.h:98
PAPI::pVec::dot
friend float dot(const pVec &a, const pVec &b)
Definition: pVec.h:95
PAPI::pVec::x
const float & x() const
Definition: pVec.h:72
PAPI::pVec::y
float & y()
Definition: pVec.h:77
PAPI::pVec::operator-
pVec operator-(const pVec &a) const
Definition: pVec.h:108
PAPI::pVec::operator==
bool operator==(const pVec &a) const
Definition: pVec.h:110
PAPI::pVec::operator*=
pVec & operator*=(const float a)
Definition: pVec.h:136
PAPI::pVec::x
float & x()
Definition: pVec.h:76
PAPI::pVec::length
float length() const
Definition: pVec.h:80
PAPI::pVec::y
const float & y() const
Definition: pVec.h:73
PAPI::pVec::lenSqr
float lenSqr() const
Definition: pVec.h:82
PAPI::pVec::operator/
pVec operator/(const float s) const
Definition: pVec.h:100
PAPI::pVec::z
const float & z() const
Definition: pVec.h:74
PAPI::pVec::z
float & z()
Definition: pVec.h:78
PAPI::pVec::Cross
friend pVec Cross(const pVec &a, const pVec &b)
Definition: pVec.h:161
PAPI
PAPIClasses.h.
Definition: pAPIContext.h:16
PAPI::pRandf
float pRandf()
Definition: pVec.h:34
PAPI::pDomainType_E
pDomainType_E
Enums for the different types of domains that can be stored in a pDomain.
Definition: pDomain.h:22
PAPI::PDCylinder_e
@ PDCylinder_e
Definition: pDomain.h:31
PAPI::PDPlane_e
@ PDPlane_e
Definition: pDomain.h:29
PAPI::PDBlob_e
@ PDBlob_e
Definition: pDomain.h:34
PAPI::PDCone_e
@ PDCone_e
Definition: pDomain.h:32
PAPI::PDTriangle_e
@ PDTriangle_e
Definition: pDomain.h:26
PAPI::PDPoint_e
@ PDPoint_e
Definition: pDomain.h:24
PAPI::PDDisc_e
@ PDDisc_e
Definition: pDomain.h:28
PAPI::PDSphere_e
@ PDSphere_e
Definition: pDomain.h:33
PAPI::PDRectangle_e
@ PDRectangle_e
Definition: pDomain.h:27
PAPI::PDBox_e
@ PDBox_e
Definition: pDomain.h:30
PAPI::PDLine_e
@ PDLine_e
Definition: pDomain.h:25
PAPI::PDUnion_e
@ PDUnion_e
Definition: pDomain.h:23
PAPI::pNRandVec
pVec pNRandVec(float sigma)
Definition: pVec.h:179
PAPI::P_ONEOVERSQRT2PI
const float P_ONEOVERSQRT2PI
Definition: pVec.h:25
PAPI::fsqr
float fsqr(float f)
Definition: pVec.h:27
PAPI::pRandVec
pVec pRandVec()
Definition: pVec.h:177
P_PLANAR_EPSILON
#define P_PLANAR_EPSILON
< How small the dot product must be to declare that a point is in a plane for Within().
Definition: pDomain.h:19
PINLINE
#define PINLINE
Definition: pVec.h:20
M_PI
#define M_PI
PVec.h - yet another 3D vector class.
Definition: pVec.h:14
PAPI::PDBlob
Gaussian blob.
Definition: pDomain.h:887
PAPI::PDBlob::Scale2
float Scale2
Definition: pDomain.h:889
PAPI::PDBlob::PDBlob
PDBlob(const pVec &Center, const float StandardDev)
Definition: pDomain.h:891
PAPI::PDBlob::PDBlob_Cons
void PDBlob_Cons(const pVec &Center, const float StandardDev)
Definition: pDomain.h:897
PAPI::PDBlob::Size
float Size() const
Returns the probability density integral, which is 1.0.
Definition: pDomain.h:918
PAPI::PDBlob::Scale1
float Scale1
Definition: pDomain.h:889
PAPI::PDBlob::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:923
PAPI::PDBlob::stdev
float stdev
Definition: pDomain.h:889
PAPI::PDBlob::ctr
pVec ctr
Definition: pDomain.h:888
PAPI::PDBlob::Within
bool Within(const pVec &pos) const
Has a probability of returning true equal to the probability density at the specified point.
Definition: pDomain.h:906
PAPI::PDBlob::Generate
pVec Generate() const
Returns a point with normal probability density.
Definition: pDomain.h:913
PAPI::PDBox
Axis-aligned bounding box (AABB)
Definition: pDomain.h:523
PAPI::PDBox::PDBox_Cons
void PDBox_Cons(const pVec &e0, const pVec &e1)
Definition: pDomain.h:534
PAPI::PDBox::dif
pVec dif
Definition: pDomain.h:525
PAPI::PDBox::p0
pVec p0
Definition: pDomain.h:525
PAPI::PDBox::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:566
PAPI::PDBox::vol
float vol
Definition: pDomain.h:526
PAPI::PDBox::PDBox
PDBox(const pVec &e0, const pVec &e1)
Definition: pDomain.h:528
PAPI::PDBox::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:568
PAPI::PDBox::p1
pVec p1
Definition: pDomain.h:525
PAPI::PDBox::Within
bool Within(const pVec &pos) const
Returns true if the point is in the box.
Definition: pDomain.h:555
PAPI::PDBox::Generate
pVec Generate() const
Returns a random point in this box.
Definition: pDomain.h:560
PAPI::PDCone
Cone.
Definition: pDomain.h:690
PAPI::PDCone::radInSqr
float radInSqr
Definition: pDomain.h:692
PAPI::PDCone::radOutSqr
float radOutSqr
Definition: pDomain.h:692
PAPI::PDCone::ThinShell
bool ThinShell
Definition: pDomain.h:693
PAPI::PDCone::radIn
float radIn
Definition: pDomain.h:692
PAPI::PDCone::radOut
float radOut
Definition: pDomain.h:692
PAPI::PDCone::PDCone_Cons
void PDCone_Cons(const pVec &e0, const pVec &e1, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:703
PAPI::PDCone::u
pVec u
Definition: pDomain.h:691
PAPI::PDCone::axisLenInvSqr
float axisLenInvSqr
Definition: pDomain.h:692
PAPI::PDCone::Size
float Size() const
Returns the thick conical shell volume or the thin conical shell area if OuterRadius==InnerRadius.
Definition: pDomain.h:794
PAPI::PDCone::v
pVec v
Definition: pDomain.h:691
PAPI::PDCone::vol
float vol
Definition: pDomain.h:692
PAPI::PDCone::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:799
PAPI::PDCone::PDCone
PDCone(const pVec &e0, const pVec &e1, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:695
PAPI::PDCone::axis
pVec axis
Definition: pDomain.h:691
PAPI::PDCone::apex
pVec apex
Definition: pDomain.h:691
PAPI::PDCone::radDif
float radDif
Definition: pDomain.h:692
PAPI::PDCone::Within
bool Within(const pVec &pos) const
Returns true if the point is within the conical shell.
Definition: pDomain.h:749
PAPI::PDCone::Generate
pVec Generate() const
Returns a random point in the conical shell.
Definition: pDomain.h:775
PAPI::PDCylinder
Cylinder.
Definition: pDomain.h:577
PAPI::PDCylinder::radInSqr
float radInSqr
Definition: pDomain.h:579
PAPI::PDCylinder::radOutSqr
float radOutSqr
Definition: pDomain.h:579
PAPI::PDCylinder::ThinShell
bool ThinShell
Definition: pDomain.h:580
PAPI::PDCylinder::radIn
float radIn
Definition: pDomain.h:579
PAPI::PDCylinder::radOut
float radOut
Definition: pDomain.h:579
PAPI::PDCylinder::u
pVec u
Definition: pDomain.h:578
PAPI::PDCylinder::axisLenInvSqr
float axisLenInvSqr
Definition: pDomain.h:579
PAPI::PDCylinder::Size
float Size() const
Returns the thick cylindrical shell volume or the thin cylindrical shell area if OuterRadius==InnerRa...
Definition: pDomain.h:673
PAPI::PDCylinder::v
pVec v
Definition: pDomain.h:578
PAPI::PDCylinder::vol
float vol
Definition: pDomain.h:579
PAPI::PDCylinder::PDCylinder_Cons
void PDCylinder_Cons(const pVec &e0, const pVec &e1, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:590
PAPI::PDCylinder::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:678
PAPI::PDCylinder::axis
pVec axis
Definition: pDomain.h:578
PAPI::PDCylinder::apex
pVec apex
Definition: pDomain.h:578
PAPI::PDCylinder::PDCylinder
PDCylinder(const pVec &e0, const pVec &e1, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:582
PAPI::PDCylinder::radDif
float radDif
Definition: pDomain.h:579
PAPI::PDCylinder::Within
bool Within(const pVec &pos) const
Returns true if the point is within the cylindrical shell.
Definition: pDomain.h:634
PAPI::PDCylinder::Generate
pVec Generate() const
Returns a random point in the cylindrical shell.
Definition: pDomain.h:658
PAPI::PDDisc
Arbitrarily-oriented disc.
Definition: pDomain.h:392
PAPI::PDDisc::PDDisc
PDDisc(const pVec &Center, const pVec Normal, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:396
PAPI::PDDisc::radInSqr
float radInSqr
Definition: pDomain.h:394
PAPI::PDDisc::radOutSqr
float radOutSqr
Definition: pDomain.h:394
PAPI::PDDisc::radIn
float radIn
Definition: pDomain.h:394
PAPI::PDDisc::radOut
float radOut
Definition: pDomain.h:394
PAPI::PDDisc::p
pVec p
Definition: pDomain.h:393
PAPI::PDDisc::dif
float dif
Definition: pDomain.h:394
PAPI::PDDisc::u
pVec u
Definition: pDomain.h:393
PAPI::PDDisc::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:464
PAPI::PDDisc::v
pVec v
Definition: pDomain.h:393
PAPI::PDDisc::area
float area
Definition: pDomain.h:394
PAPI::PDDisc::D
float D
Definition: pDomain.h:394
PAPI::PDDisc::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:469
PAPI::PDDisc::PDDisc_Cons
void PDDisc_Cons(const pVec &Center, const pVec Normal, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:404
PAPI::PDDisc::nrm
pVec nrm
Definition: pDomain.h:393
PAPI::PDDisc::Within
bool Within(const pVec &pos) const
Returns true for points within epsilon of the disc.
Definition: pDomain.h:439
PAPI::PDDisc::Generate
pVec Generate() const
Returns a point inside the disc shell.
Definition: pDomain.h:450
PAPI::PDLine
A line segment.
Definition: pDomain.h:207
PAPI::PDLine::vecNrm
pVec vecNrm
Definition: pDomain.h:208
PAPI::PDLine::p0
pVec p0
Definition: pDomain.h:208
PAPI::PDLine::vec
pVec vec
Definition: pDomain.h:208
PAPI::PDLine::PDLine_Cons
void PDLine_Cons(const pVec &e0, const pVec &e1)
Definition: pDomain.h:217
PAPI::PDLine::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:240
PAPI::PDLine::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:242
PAPI::PDLine::p1
pVec p1
Definition: pDomain.h:208
PAPI::PDLine::PDLine
PDLine(const pVec &e0, const pVec &e1)
Definition: pDomain.h:211
PAPI::PDLine::len
float len
Definition: pDomain.h:209
PAPI::PDLine::Within
bool Within(const pVec &pos) const
Returns true for points within epsilon of the line segment.
Definition: pDomain.h:227
PAPI::PDLine::Generate
pVec Generate() const
Returns a random point on this segment.
Definition: pDomain.h:235
PAPI::PDPlane
Arbitrarily-oriented plane.
Definition: pDomain.h:478
PAPI::PDPlane::p
pVec p
Definition: pDomain.h:479
PAPI::PDPlane::PDPlane_Cons
void PDPlane_Cons(const pVec &p0, const pVec &Normal)
Definition: pDomain.h:488
PAPI::PDPlane::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:510
PAPI::PDPlane::D
float D
Definition: pDomain.h:480
PAPI::PDPlane::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:515
PAPI::PDPlane::nrm
pVec nrm
Definition: pDomain.h:479
PAPI::PDPlane::PDPlane
PDPlane(const pVec &p0, const pVec &Normal)
Definition: pDomain.h:482
PAPI::PDPlane::Within
bool Within(const pVec &pos) const
Returns true if the point is in the positive half-space of the plane (in the plane or on the side tha...
Definition: pDomain.h:499
PAPI::PDPlane::Generate
pVec Generate() const
Returns the point p0.
Definition: pDomain.h:505
PAPI::PDPoint
A single point.
Definition: pDomain.h:176
PAPI::PDPoint::PDPoint_Cons
void PDPoint_Cons(const pVec &p0)
Definition: pDomain.h:185
PAPI::PDPoint::p
pVec p
Definition: pDomain.h:177
PAPI::PDPoint::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:197
PAPI::PDPoint::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:199
PAPI::PDPoint::PDPoint
PDPoint(const pVec &p0)
Definition: pDomain.h:179
PAPI::PDPoint::Within
bool Within(const pVec &pos) const
Returns true if the point is exactly equal.
Definition: pDomain.h:187
PAPI::PDPoint::Generate
pVec Generate() const
Returns the point.
Definition: pDomain.h:192
PAPI::PDRectangle
Rhombus-shaped planar region.
Definition: pDomain.h:325
PAPI::PDRectangle::uLen
float uLen
Definition: pDomain.h:327
PAPI::PDRectangle::PDRectangle_Cons
void PDRectangle_Cons(const pVec &p0, const pVec &u0, const pVec &v0)
Definition: pDomain.h:335
PAPI::PDRectangle::uNrm
pVec uNrm
Definition: pDomain.h:326
PAPI::PDRectangle::p
pVec p
Definition: pDomain.h:326
PAPI::PDRectangle::vNrm
pVec vNrm
Definition: pDomain.h:326
PAPI::PDRectangle::u
pVec u
Definition: pDomain.h:326
PAPI::PDRectangle::vLen
float vLen
Definition: pDomain.h:327
PAPI::PDRectangle::PDRectangle
PDRectangle(const pVec &p0, const pVec &u0, const pVec &v0)
Definition: pDomain.h:329
PAPI::PDRectangle::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:381
PAPI::PDRectangle::v
pVec v
Definition: pDomain.h:326
PAPI::PDRectangle::area
float area
Definition: pDomain.h:327
PAPI::PDRectangle::D
float D
Definition: pDomain.h:327
PAPI::PDRectangle::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:383
PAPI::PDRectangle::nrm
pVec nrm
Definition: pDomain.h:326
PAPI::PDRectangle::s1
pVec s1
Definition: pDomain.h:326
PAPI::PDRectangle::s2
pVec s2
Definition: pDomain.h:326
PAPI::PDRectangle::Within
bool Within(const pVec &pos) const
Returns true for points within epsilon of the patch.
Definition: pDomain.h:359
PAPI::PDRectangle::Generate
pVec Generate() const
Returns a random point in the diamond-shaped patch whose corners are o, o+u, o+u+v,...
Definition: pDomain.h:375
PAPI::PDSphere
Sphere.
Definition: pDomain.h:808
PAPI::PDSphere::radInSqr
float radInSqr
Definition: pDomain.h:810
PAPI::PDSphere::radOutSqr
float radOutSqr
Definition: pDomain.h:810
PAPI::PDSphere::ThinShell
bool ThinShell
Definition: pDomain.h:811
PAPI::PDSphere::radIn
float radIn
Definition: pDomain.h:810
PAPI::PDSphere::radOut
float radOut
Definition: pDomain.h:810
PAPI::PDSphere::PDSphere_Cons
void PDSphere_Cons(const pVec &Center, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:821
PAPI::PDSphere::Size
float Size() const
Returns the thick spherical shell volume or the thin spherical shell area if OuterRadius==InnerRadius...
Definition: pDomain.h:873
PAPI::PDSphere::vol
float vol
Definition: pDomain.h:810
PAPI::PDSphere::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:878
PAPI::PDSphere::PDSphere
PDSphere(const pVec &Center, const float OuterRadius, const float InnerRadius=0.0f)
Definition: pDomain.h:813
PAPI::PDSphere::radDif
float radDif
Definition: pDomain.h:810
PAPI::PDSphere::ctr
pVec ctr
Definition: pDomain.h:809
PAPI::PDSphere::Within
bool Within(const pVec &pos) const
Returns true if the point lies within the thick shell.
Definition: pDomain.h:848
PAPI::PDSphere::Generate
pVec Generate() const
Returns a random point in the thick spherical shell.
Definition: pDomain.h:855
PAPI::PDTriangle
A Triangle.
Definition: pDomain.h:252
PAPI::PDTriangle::uLen
float uLen
Definition: pDomain.h:254
PAPI::PDTriangle::PDTriangle
PDTriangle(const pVec &p0, const pVec &p1, const pVec &p2)
Definition: pDomain.h:256
PAPI::PDTriangle::uNrm
pVec uNrm
Definition: pDomain.h:253
PAPI::PDTriangle::p
pVec p
Definition: pDomain.h:253
PAPI::PDTriangle::vNrm
pVec vNrm
Definition: pDomain.h:253
PAPI::PDTriangle::u
pVec u
Definition: pDomain.h:253
PAPI::PDTriangle::vLen
float vLen
Definition: pDomain.h:254
PAPI::PDTriangle::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:315
PAPI::PDTriangle::v
pVec v
Definition: pDomain.h:253
PAPI::PDTriangle::area
float area
Definition: pDomain.h:254
PAPI::PDTriangle::D
float D
Definition: pDomain.h:254
PAPI::PDTriangle::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:317
PAPI::PDTriangle::nrm
pVec nrm
Definition: pDomain.h:253
PAPI::PDTriangle::s1
pVec s1
Definition: pDomain.h:253
PAPI::PDTriangle::s2
pVec s2
Definition: pDomain.h:253
PAPI::PDTriangle::Within
bool Within(const pVec &pos) const
Returns true for points within epsilon of the triangle.
Definition: pDomain.h:286
PAPI::PDTriangle::Generate
pVec Generate() const
Returns a random point in the triangle.
Definition: pDomain.h:302
PAPI::PDTriangle::PDTriangle_Cons
void PDTriangle_Cons(const pVec &p0, const pVec &p1, const pVec &p2)
Definition: pDomain.h:262
PAPI::PDUnion
A CSG union of multiple domains.
Definition: pDomain.h:93
PAPI::PDUnion::PDUnion
PDUnion(const std::vector< std::shared_ptr< pDomain > > &DomList)
Makes a copy of all the subdomains and point to the copies.
Definition: pDomain.h:123
PAPI::PDUnion::PDUnion
PDUnion()
Use this one to create an empty PDUnion then call .insert() to add each item to it.
Definition: pDomain.h:97
PAPI::PDUnion::PDUnion
PDUnion(const pDomain &A, const pDomain &B, const pDomain &C)
Definition: pDomain.h:111
PAPI::PDUnion::PDUnion
PDUnion(const pDomain &A, const pDomain &B)
Definition: pDomain.h:103
PAPI::PDUnion::Doms
std::vector< std::shared_ptr< pDomain > > Doms
Definition: pDomain.h:94
PAPI::PDUnion::Size
float Size() const
Returns the size of the domain (length, area, or volume).
Definition: pDomain.h:168
PAPI::PDUnion::copy
std::shared_ptr< pDomain > copy() const
Definition: pDomain.h:170
PAPI::PDUnion::insert
void insert(const pDomain &A)
Insert another domain into this PDUnion.
Definition: pDomain.h:145
PAPI::PDUnion::PDUnion
PDUnion(const PDUnion &P)
Makes a copy of all the subdomains and point to the copies.
Definition: pDomain.h:134
PAPI::PDUnion::TotalSize
float TotalSize
Definition: pDomain.h:95
PAPI::PDUnion::Within
bool Within(const pVec &pos) const
Returns true if pos is within any of the domains.
Definition: pDomain.h:151
PAPI::PDUnion::Generate
pVec Generate() const
Generate a point in any subdomain, chosen by the ratio of their sizes.
Definition: pDomain.h:158
PAPI::PErrInternalError
Internal API error (a PASSERT failed)
Definition: pError.h:28
PAPI::PErrInternalError::PErrInternalError
PErrInternalError(const std::string Er)
Definition: pError.h:29
PAPI::PErrInvalidValue
An invalid value was passed to an API call.
Definition: pError.h:40
PAPI::PErrInvalidValue::PErrInvalidValue
PErrInvalidValue(const std::string Er)
Definition: pError.h:41