mirror of
https://github.com/cosinekitty/astronomy.git
synced 2025-12-31 03:30:26 -05:00
114 lines
4.4 KiB
C++
114 lines
4.4 KiB
C++
/*
|
|
solid.cpp
|
|
|
|
Copyright (C) 2013 by Don Cross - http://cosinekitty.com/raytrace
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the author be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source
|
|
distribution.
|
|
|
|
-------------------------------------------------------------------------
|
|
Contains common code for base class SolidObject.
|
|
*/
|
|
|
|
#include "imager.h"
|
|
|
|
namespace Imager
|
|
{
|
|
bool SolidObject::Contains(const Vector& point) const
|
|
{
|
|
// FIXFIXFIX: This function does not handle the "corner case":
|
|
// multiple intersections found at the same point but for
|
|
// different facets of the solid.
|
|
|
|
if (isFullyEnclosed)
|
|
{
|
|
// This method assumes that the solid's surfaces fully
|
|
// enclose a volume of space without any gaps or cracks.
|
|
// Pick an arbitrary direction in space and count the number
|
|
// of times we enter and exit this solid.
|
|
const Vector direction(0.0, 0.0, 1.0);
|
|
|
|
enclosureList.clear();
|
|
AppendAllIntersections(point, direction, enclosureList);
|
|
|
|
int enterCount = 0; // number of times we enter the solid
|
|
int exitCount = 0; // number of times we exit the solid
|
|
|
|
IntersectionList::const_iterator iter = enclosureList.begin();
|
|
IntersectionList::const_iterator end = enclosureList.end();
|
|
for (; iter != end; ++iter)
|
|
{
|
|
const Intersection& intersection = *iter;
|
|
|
|
// Calculate the dot product of the direction with
|
|
// the surface normal.
|
|
const double dotprod = DotProduct(
|
|
direction,
|
|
intersection.surfaceNormal);
|
|
|
|
// If it is positive, we are exiting the solid.
|
|
// If it is negative, we are entering the solid.
|
|
if (dotprod > EPSILON)
|
|
{
|
|
++exitCount;
|
|
}
|
|
else if (dotprod < -EPSILON)
|
|
{
|
|
++enterCount;
|
|
}
|
|
else
|
|
{
|
|
// If the dot product is too close to zero,
|
|
// something odd is going on because we
|
|
// should not have found an intersection
|
|
// with a plane in the first place.
|
|
throw ImagerException("Ambiguous transition.");
|
|
}
|
|
}
|
|
|
|
// If the original point is within this solid,
|
|
// we have exited the object one more time than we entered.
|
|
// Otherwise, we have exited and entered the same number of times.
|
|
switch (exitCount - enterCount)
|
|
{
|
|
case 0:
|
|
return false; // point is outside the solid
|
|
|
|
case 1:
|
|
return true; // point is inside the solid
|
|
|
|
default:
|
|
// This can happen only if the solid's surfaces
|
|
// do not properly enclose a volume of space without
|
|
// gaps. Either the surfaces need to be corrected
|
|
// so as to perfectly seal the interior volume
|
|
// or this instance should be constructed with
|
|
// isFullyEnclosed initialized to false.
|
|
throw ImagerException("Cannot determine containment.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Whoever constructed this object has indicated that
|
|
// it should not be considered to contain any points.
|
|
return false;
|
|
}
|
|
}
|
|
}
|