Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 确定一个矩形是否比另一个矩形更接近一个圆_Algorithm_Computational Geometry_Geometry_Rectangles - Fatal编程技术网

Algorithm 确定一个矩形是否比另一个矩形更接近一个圆

Algorithm 确定一个矩形是否比另一个矩形更接近一个圆,algorithm,computational-geometry,geometry,rectangles,Algorithm,Computational Geometry,Geometry,Rectangles,假设我们有两个矩形A,B和一个圆R。我们想确定,对于任意三个点R,A,B,“R\in R,A\in A,B\in B”,“dist(R,A)那么代码> A-R

假设我们有两个矩形A,B和一个圆R。我们想确定,对于任意三个点R,A,B,“R\in R,A\in A,B\in B”,“dist(R,A) 请注意,矩形和圆可以是高维空间中的超矩形和超球体,并且矩形与轴平行

是否有多项式时间内运行的测试算法(关于维数D)?O(D)可能吗


PS:测试应该是可靠和完整的,即没有假阳性或真阴性首先,因为我们在N维空间中工作,所以我们将这些对象称为
NBox
NBall
。这些定义了N维体积

假设长方体的轴与欧几里德空间的标准单位向量对齐,则
NBox
可以表示为沿坐标轴的两个N维双数组
Min
Max
,或者表示为坐标轴上的单个N维
Range
投影列表。
NBall
可以表示为单个N维双数组
Center
和双
Radius
。一个
NPoint
,一个单一的N维点,像这样(在c#中):

既然我们知道了如何计算长方体和点之间的最近点,那么就很容易得到长方体、点和球之间的距离。两点和/或长方体之间的距离是最近点之间的距离,如果它们相交,则为零。
NBall
与方框或点之间的距离是最近点之间的距离,小于半径,如果差值为负值(交点),则为零


我可以想到一个算法,它涉及所有的面和矩形(或超立方体)的顶点。因此,不幸的是,它在维数上是指数型的。但至少它应该是正确的

引理1 给定点p。给定矩形内最近的点是p本身或重角边界/曲面上的另一点

引理2 给定点p。给定矩形内最远的点是其中一个顶点(角)

所以,如果我们想检查矩形A是否比矩形B更接近圆R,那么我们搜索一个反例。如果我们找不到,A就更近了

假设存在这样一个反例(r,a,b)。然后我们可以将点a移得更远,b移得更近,得到一个更“强大”的反例。 我们只检查这些“最强”的潜在反例。 因此,如果r中有一个点r,a中最远的点不比B中最近的点近,那么a就不比r近。但是如果我们找不到这样的点r,那么a就更接近r,根据jojer的条件

如引理1所述,我们只检查b的每个曲面(2d中的边)上的b点。 根据引理2,我们只检查a顶点的a点

如果我们现在检查所有这些a点和所有这些b点,将空间分成两半,并显示圆完全位于靠近a的那一半,那么就没有反例了

空间分割是2个超平面和一个超抛物线的合成(如果我们将a的顶点与B的曲面进行对比),请参见示例:

因此,我们构造所有这些分割平面/抛物面,并测试圆心的方向距离是否大于其半径。 如果是这样的话,那么就不可能有三元组(r,a,b)构成反例


整个过程应该只是对一些二次型的求值,主要是顶点对和顶点曲面对的数量,它们在维数上是指数级的。

嗨,我不太明白“如果中心更靠近一个矩形,那么圆就更近。”实际上,距离(a,r)及(b,r)区因为A和B应该连接到同一点R。我的意思是,你不需要考虑你的圆的半径。如果你知道你的圆的中心,只需要从中心到每个矩形的距离,并且减去你的半径,得到实际的距离。但是,既然你只关心哪个更近,你就不知道。如果是<代码> a < b>代码>那么代码> A-R 你不能只考虑中心。下面的例子:根据你的条件,圆圈更靠近左边的矩形。但是在圆圈内有一个点,与另一个矩形的最小距离比第一个小,所以没有一个。根据jojers条件,cangles更接近圆。哦,我想我误解了。所以OP想测试R中的每一点是否比B中的任何一点更接近A中的每一点,或者反之亦然?从你对答案的评论来看,“如果A比B更接近R”有不同的“更接近”定义你能在不使用数学关联的情况下勾勒出它的轮廓吗?例如,如果你把矩形放在一个轴上,那么
public interface INDimensional
{
    int Dimension { get; }
}

public class NPoint : INDimensional
{
    readonly double[] point;

    public NPoint(double[] point)
    {
        if (point == null)
            throw new ArgumentNullException();
        if (point.Length < 1)
            throw new ArgumentException();
        this.point = point.ToArray(); // copy
    }

    public int Dimension { get { return point.Length; } }

    public double this[int i] { get { return point[i]; } }

    public IList<double> Coordinates { get { return Array.AsReadOnly(point); } }
}

public class NBall : INDimensional
{
    readonly NPoint center;
    readonly double radius;

    public NBall(double[] center, double radius)
    {
        if (Math.Abs(radius) < Accuracy.AbsoluteDoubleTolerance)
            this.radius = 0;
        else if (radius < 0)
            throw new ArgumentException();
        else
            this.radius = radius;
        this.center = new NPoint(center);
        this.radius = radius;
    }

    public int Dimension { get { return center.Dimension; } }

    public double this[int i] { get { return center[i]; } }

    public NPoint Center { get { return center; } }

    public double Radius { get { return radius; } }
}

public class NBox : INDimensional
{
    readonly double[] min;
    readonly double[] max;

    static void ComputeExtremes(double[] point1, double[] point2, out double[] min, out double[] max)
    {
        if (point1 == null || point2 == null)
            throw new NullReferenceException();
        if (point1.Length != point2.Length)
            throw new ArgumentException();
        min = new double[point1.Length];
        max = new double[point1.Length];
        for (int i = 0; i < point1.Length; i++)
        {
            // Handle double-precision rounding issues where point1[i] and point2[i] so nearly equal that they somehow got inverted.
            min[i] = Math.Min(point1[i], point2[i]);
            max[i] = Math.Max(point1[i], point2[i]);
        }
    }

    public NBox(double[] min, double[] max)
    {
        ComputeExtremes(min, max, out this.min, out this.max);
    }

    public int Dimension { get { return min.Length; } }

    public Range<double> this[int i] { get { return new Range<double>(min[i], max[i]); } }

    public IList<double> Min { get { return Array.AsReadOnly(min); } }

    public IList<double> Max { get { return Array.AsReadOnly(max); } }
}
public static class NDimensionalExtensions 
{
    public static bool FindClosest(this Range<double> range, double other, out double closestParameter)
    {
        if (other <= range.Min)
        {
            closestParameter = range.Min;
            return false;
        }
        if (other >= range.Max)
        {
            closestParameter = range.Max;
            return false;
        }
        closestParameter = other;
        return true;
    }
}

public class NBox 
{
    public bool FindClosest(NPoint other, out NPoint closestPoint)
    {
        if (other.Dimension != Dimension)
            throw new ArgumentException();
        double[] closest = new double[other.Dimension];
        bool allInside = true;
        for (int i = 0; i < Dimension; i++)
        {
            allInside = allInside && this[i].FindClosest(other[i], out closest[i]);
        }
        closestPoint = new NPoint(closest);
        return allInside;
    }
}
public static class NDimensionalExtensions 
{
    public static bool FindClosest(this Range<double> range, Range<double> other, out double closestParameter)
    {
        if (other.Max <= range.Min)
        {
            closestParameter =range.Min;
            return false;
        }
        else if (other.Min >= range.Max)
        {
            closestParameter = range.Max;
            return false;
        }
        // return in the middle of the overlap
        closestParameter = 0.5 * Math.Max(range.Min, other.Min) + 0.5 * Math.Min(range.Max, other.Max);
        return true;
    }
}

public class NBox 
{
    public bool FindClosest(NBox other, out NPoint closestPoint)
    {
        if (other.Dimension != Dimension)
            throw new ArgumentException();
        double[] closest = new double[other.Dimension];
        bool allInside = true;
        for (int i = 0; i < Dimension; i++)
        {
            allInside = allInside && this[i].FindClosest(other[i], out closest[i]);
        }
        closestPoint = new NPoint(closest);
        return allInside;
    }
}
public interface INDimensional
{
    double GetDistance(NBox other);
}

public class NPoint : INDimensional
{
    public double GetDistance(NPoint other)
    {
        if (Dimension != other.Dimension)
            throw new ArgumentException();
        double distSq = 0;
        for (int i = 0; i < Dimension; i++)
        {
            var dot = (this[i] - other[i]);
            distSq += dot * dot;
        }
        return Math.Sqrt(distSq);
    }

    public double GetDistance(NBox other)
    {
        NPoint closestPoint;
        if (other.FindClosest(this, out closestPoint))
            return 0;
        return GetDistance(closestPoint);
    }
}

public class NBall : INDimensional
{
    public double GetDistance(NBox other)
    {
        NPoint closestPoint;
        var allInside = other.FindClosest(Center, out closestPoint);
        if (allInside)
            return 0;
        double distance = closestPoint.GetDistance(Center) - Radius;
        if (distance < 0)
            distance = 0;
        return distance;
    }
}

public class NBox : INDimensional
{
    public bool FindClosest(NBox other, out NPoint closestPoint)
    {
        if (other.Dimension != Dimension)
            throw new ArgumentException();
        double[] closest = new double[other.Dimension];
        bool allInside = true;
        for (int i = 0; i < Dimension; i++)
        {
            allInside = allInside && this[i].FindClosest(other[i], out closest[i]);
        }
        closestPoint = new NPoint(closest);
        return allInside;
    }

    public double GetDistance(NBox other)
    {
        NPoint myClosest, boxClosest;
        if (FindClosest(other, out myClosest))
            return 0;
        if (other.FindClosest(this, out boxClosest))
            return 0;
        return myClosest.GetDistance(boxClosest);
    }
}
public static class Accuracy
{
    public static double AbsoluteDoubleTolerance
    {
        get
        {
            return 100 * double.Epsilon;
        }
    }
}