You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
5.5 KiB
159 lines
5.5 KiB
// David Eberly, Geometric Tools, Redmond WA 98052
|
|
// Copyright (c) 1998-2021
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// https://www.boost.org/LICENSE_1_0.txt
|
|
// https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
|
|
// Version: 4.0.2019.08.13
|
|
|
|
#pragma once
|
|
|
|
#include <Mathematics/FIQuery.h>
|
|
#include <Mathematics/Halfspace.h>
|
|
#include <Mathematics/OrientedBox.h>
|
|
#include <Mathematics/Vector2.h>
|
|
#include <vector>
|
|
|
|
// The queries consider the box to be a solid and the polygon to be a
|
|
// convex solid.
|
|
|
|
namespace gte
|
|
{
|
|
template <typename Real>
|
|
class FIQuery<Real, Halfspace<2, Real>, std::vector<Vector2<Real>>>
|
|
{
|
|
public:
|
|
struct Result
|
|
{
|
|
bool intersect;
|
|
|
|
// If 'intersect' is true, the halfspace and polygon intersect
|
|
// in a convex polygon.
|
|
std::vector<Vector2<Real>> polygon;
|
|
};
|
|
|
|
Result operator()(Halfspace<2, Real> const& halfspace,
|
|
std::vector<Vector2<Real>> const& polygon)
|
|
{
|
|
Result result;
|
|
|
|
// Determine whether the polygon vertices are outside the
|
|
// halfspace, inside the halfspace, or on the halfspace boundary.
|
|
int const numVertices = static_cast<int>(polygon.size());
|
|
std::vector<Real> distance(numVertices);
|
|
int positive = 0, negative = 0, positiveIndex = -1;
|
|
for (int i = 0; i < numVertices; ++i)
|
|
{
|
|
distance[i] = Dot(halfspace.normal, polygon[i]) - halfspace.constant;
|
|
if (distance[i] > (Real)0)
|
|
{
|
|
++positive;
|
|
if (positiveIndex == -1)
|
|
{
|
|
positiveIndex = i;
|
|
}
|
|
}
|
|
else if (distance[i] < (Real)0)
|
|
{
|
|
++negative;
|
|
}
|
|
}
|
|
|
|
if (positive == 0)
|
|
{
|
|
// The polygon is strictly outside the halfspace.
|
|
result.intersect = false;
|
|
return result;
|
|
}
|
|
|
|
if (negative == 0)
|
|
{
|
|
// The polygon is contained in the closed halfspace, so it is
|
|
// fully visible and no clipping is necessary.
|
|
result.intersect = true;
|
|
return result;
|
|
}
|
|
|
|
// The line transversely intersects the polygon. Clip the polygon.
|
|
Vector2<Real> vertex;
|
|
int curr, prev;
|
|
Real t;
|
|
|
|
if (positiveIndex > 0)
|
|
{
|
|
// Compute the first clip vertex on the line.
|
|
curr = positiveIndex;
|
|
prev = curr - 1;
|
|
t = distance[curr] / (distance[curr] - distance[prev]);
|
|
vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
|
|
result.polygon.push_back(vertex);
|
|
|
|
// Include the vertices on the positive side of line.
|
|
while (curr < numVertices && distance[curr] >(Real)0)
|
|
{
|
|
result.polygon.push_back(polygon[curr++]);
|
|
}
|
|
|
|
// Compute the kast clip vertex on the line.
|
|
if (curr < numVertices)
|
|
{
|
|
prev = curr - 1;
|
|
}
|
|
else
|
|
{
|
|
curr = 0;
|
|
prev = numVertices - 1;
|
|
}
|
|
t = distance[curr] / (distance[curr] - distance[prev]);
|
|
vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
|
|
result.polygon.push_back(vertex);
|
|
}
|
|
else // positiveIndex is 0
|
|
{
|
|
// Include the vertices on the positive side of line.
|
|
curr = 0;
|
|
while (curr < numVertices && distance[curr] >(Real)0)
|
|
{
|
|
result.polygon.push_back(polygon[curr++]);
|
|
}
|
|
|
|
// Compute the last clip vertex on the line.
|
|
prev = curr - 1;
|
|
t = distance[curr] / (distance[curr] - distance[prev]);
|
|
vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
|
|
result.polygon.push_back(vertex);
|
|
|
|
// Skip the vertices on the negative side of the line.
|
|
while (curr < numVertices && distance[curr] <= (Real)0)
|
|
{
|
|
curr++;
|
|
}
|
|
|
|
// Compute the first clip vertex on the line.
|
|
if (curr < numVertices)
|
|
{
|
|
prev = curr - 1;
|
|
t = distance[curr] / (distance[curr] - distance[prev]);
|
|
vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
|
|
result.polygon.push_back(vertex);
|
|
|
|
// Keep the vertices on the positive side of the line.
|
|
while (curr < numVertices && distance[curr] >(Real)0)
|
|
{
|
|
result.polygon.push_back(polygon[curr++]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
curr = 0;
|
|
prev = numVertices - 1;
|
|
t = distance[curr] / (distance[curr] - distance[prev]);
|
|
vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
|
|
result.polygon.push_back(vertex);
|
|
}
|
|
}
|
|
|
|
result.intersect = true;
|
|
return result;
|
|
}
|
|
};
|
|
}
|
|
|