Пересечение линейного сегмента с выровненным осью полем в C#

$_SERVER['REMOTE_ADDR'] может фактически не содержать реальных IP-адресов клиента, поскольку он даст вам прокси-адрес для клиентов, подключенных через прокси-сервер, например. Однако это может быть то, что вы действительно хотите, в зависимости от того, что вы делаете с IP-адресами. Частный адрес RFC1918 у кого-то может не принести вам пользы, если вы скажете, пытаясь узнать, откуда происходит ваш трафик, или вспомнить, какой IP-адрес был последним подключен к пользователю, где может быть больше общедоступный IP-адрес прокси-сервера или шлюза NAT

Существует несколько HTTP-заголовков, таких как X-Forwarded-For, которые могут или не могут быть заданы различными прокси-серверами. Проблема в том, что это просто HTTP-заголовки, которые могут быть установлены кем угодно. Нет никаких гарантий относительно их содержания. $_SERVER['REMOTE_ADDR'] - это фактический физический IP-адрес, на который веб-сервер получил соединение и ответ будет отправлен. Все остальное - это произвольная и добровольная информация. Существует только один сценарий, в котором вы можете доверять этой информации: вы контролируете прокси-сервер, который устанавливает этот заголовок. Значение только в том случае, если вы знаете 100%, где и как был настроен заголовок, если вы прислушаетесь к нему для чего-то важного.

Сказав это, вот пример кода:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

Редактор Примечание. Использование вышеуказанного кода имеет последствия для безопасности. Клиент может настроить всю информацию заголовка HTTP (т.е. $_SERVER['HTTP_...) на любое произвольное значение, которое он хочет. Таким образом, гораздо надежнее использовать $_SERVER['REMOTE_ADDR'], поскольку пользователь не может установить его.

От: http://roshanbh.com.np/2007/12/getting-real -ip-адрес-в-php.html

5
задан devuxer 25 June 2010 в 03:04
поделиться

3 ответа

Вот что я в итоге использовал:

public static List<Point3D> IntersectionOfLineSegmentWithAxisAlignedBox(
    Point3D segmentBegin, Point3D segmentEnd, Point3D boxCenter, Size3D boxSize)
{
    var beginToEnd = segmentEnd - segmentBegin;
    var minToMax = new Vector3D(boxSize.X, boxSize.Y, boxSize.Z);
    var min = boxCenter - minToMax / 2;
    var max = boxCenter + minToMax / 2;
    var beginToMin = min - segmentBegin;
    var beginToMax = max - segmentBegin;
    var tNear = double.MinValue;
    var tFar = double.MaxValue;
    var intersections = new List<Point3D>();
    foreach (Axis axis in Enum.GetValues(typeof(Axis)))
    {
        if (beginToEnd.GetCoordinate(axis) == 0) // parallel
        {
            if (beginToMin.GetCoordinate(axis) > 0 || beginToMax.GetCoordinate(axis) < 0)
                return intersections; // segment is not between planes
        }
        else
        {
            var t1 = beginToMin.GetCoordinate(axis) / beginToEnd.GetCoordinate(axis);
            var t2 = beginToMax.GetCoordinate(axis) / beginToEnd.GetCoordinate(axis);
            var tMin = Math.Min(t1, t2);
            var tMax = Math.Max(t1, t2);
            if (tMin > tNear) tNear = tMin;
            if (tMax < tFar) tFar = tMax;
            if (tNear > tFar || tFar < 0) return intersections;

        }
    }
    if (tNear >= 0 && tNear <= 1) intersections.Add(segmentBegin + beginToEnd * tNear);
    if (tFar >= 0 && tFar <= 1) intersections.Add(segmentBegin + beginToEnd * tFar);
    return intersections;
}

public enum Axis
{
    X,
    Y,
    Z
}

public static double GetCoordinate(this Point3D point, Axis axis)
{
    switch (axis)
    {
        case Axis.X:
            return point.X;
        case Axis.Y:
            return point.Y;
        case Axis.Z:
            return point.Z;
        default:
            throw new ArgumentException();
    }
}

public static double GetCoordinate(this Vector3D vector, Axis axis)
{
    switch (axis)
    {
        case Axis.X:
            return vector.X;
        case Axis.Y:
            return vector.Y;
        case Axis.Z:
            return vector.Z;
        default:
            throw new ArgumentException();
    }
}
4
ответ дан 14 December 2019 в 13:26
поделиться

Вот другое высокоэффективное и изящное решение.

Это записано в C++, но тривиально переводимо к Python (на ссылки на этот поток от другого ТАК вопросы) или C# (на исходную ПО). Это принимает доступ к 3D векторному классу/структуре, здесь Vector3f, с основными алгебраическими определенными операциями/операторами. В C++, чем-то как Собственный:: Vector3f может использоваться; в Python простое может использоваться массив NumPy ; и в C# может, вероятно, использоваться Vector3.

стандартная программа оптимизирована для проверки на пересечения с несколькими выровненными сеткой полями.

Определение класса сегмента с простым основанным на конечной точке конструктором:

class Segment {
public:
    Segment(const Vector3f& startPoint, const Vector3f& endPoint) :
            origin(startPoint), direction(endPoint - startPoint),
            inverseDirection(Vector3f(1.0) / direction),
            sign{(inverseDirection.x < 0),(inverseDirection.y < 0),(inverseDirection.z < 0)}
            {}

    float length(){
        return sqrtf(direction.x * direction.x + direction.y * direction.y +
                     direction.z * direction.z);
    }
    Vector3f origin, endpoint, direction;
    Vector3f inverseDirection;
    int sign[3];
};

Фактическая стандартная программа, которая выполняет проверку:

bool SegmentIntersectsGridAlignedBox3D(Segment segment, Vector3f boxMin, Vector3f boxMax){
    float tmin, tmax, tymin, tymax, tzmin, tzmax;
    Vector3f bounds[] = {boxMin, boxMax};

    tmin = (bounds[segment.sign[0]].x - segment.origin.x) * segment.inverseDirection.x;
    tmax = (bounds[1 - segment.sign[0]].x - segment.origin.x) * segment.inverseDirection.x;
    tymin = (bounds[segment.sign[1]].y - segment.origin.y) * segment.inverseDirection.y;
    tymax = (bounds[1 - segment.sign[1]].y - segment.origin.y) * segment.inverseDirection.y;

    if ((tmin > tymax) || (tymin > tmax)){
        return false;
    }
    if (tymin > tmin) {
        tmin = tymin;
    }
    if (tymax < tmax){
        tmax = tymax;
    }

    tzmin = (bounds[segment.sign[2]].z - segment.origin.z) * segment.inverseDirection.z;
    tzmax = (bounds[1 - segment.sign[2]].z - segment.origin.z) * segment.inverseDirection.z;

    if ((tmin > tzmax) || (tzmin > tmax)){
        return false;
    }
    if (tzmin > tmin){
        tmin = tzmin;
    }
    if (tzmax < tmax){
        tmax = tzmax;
    }
    // this last check is different from the 'ray' case in below references: 
    // we need to check that the segment is on the span of the line
    // that intersects the box
    return !(tmax < 0.0f || tmin > 1.0f); 
}

Кредит на этот ответ главным образом переходит к scratchpixel.com и автору лет это учебное руководство , которое является на основе:

Williams, Amy, Steve Barrus, R. Keith Morley и Peter Shirley. "Эффективный и устойчивый перекрестный алгоритм поля луча". Журнал графических инструментов 10, № 1 (2005): 49-54 ссылка

можно найти очень подробное объяснение кода в этом учебном руководстве.

Все, что я сделал, было, немного изменяют код для обращения к сегменту вдоль луча, а не проблеме пересечения лучом.

0
ответ дан 14 December 2019 в 13:26
поделиться

Ну, для выровненного по оси ящика это довольно просто: нужно найти пересечение луча с 6 плоскостями (определяемыми гранями ящика), а затем проверить найденные точки на ограничения координат вершин ящика.

2
ответ дан 14 December 2019 в 13:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: