确定线段通过的Octants

时间:2016-06-21 04:45:52

标签: c# geometry

自从我参加任何类型的数学课以来已经20多年了,所以我超级生锈了。我使用以下代码来确定一个点位于相对于提供的中心的位置:

public static int GetOctant(Vector2 center, Vector2 target)
{
    var adjusted = target - center;
    int oct = 0;

    if (adjusted.Y < 0)
    {
        adjusted *= -1; // rotate 180
        oct += 4;
    }
    if (adjusted.X < 0)
    {
        adjusted = new Vector2(adjusted.Y, -adjusted.X); // rotate cw 90
        oct += 2;
    }
    if (adjusted.X < adjusted.Y)
        oct++;

    return oct;
}

我为我的两行做了这个,这给了我开始和结束的八分圆。 如果它们相隔超过1个八分之一,那么我还需要知道这条线经过的其他八分圆。但我无法弄清楚如何做到这一点。

我希望有这样的方法:

private static int[] InOctants(Vector2 relativeCenter, Vector2 startPoint, Vector2 endPoint)

private static bool IsInOctant(int oct, Vector2 center, Vector2 startPoint, Vector2 endPoint)

我的代码(非常非数学)看起来像这样(Segment只有2 Vectors2):

private static List<Segment>[] PlaceInOctants(Vector2 center, IEnumerable<Segment> segments)
{
    // We are creating lists of segments, 1 for each octant.
    // Each list will contain any segment that touches that octant
    var octants = new List<Segment>[8];
    for (int i = 0; i < octants.Length; i++)
        octants[i] = new List<Segment>();

    foreach (Segment s in segments)
    {
        // Get the octant for the start/end points of the segments
        var octantA = GetOctant(center, s.PointA);
        var octantB = GetOctant(center, s.PointB);
        if (octantA > octantB)
        {
            var tempOct = octantA;
            octantA = octantB;
            octantB = tempOct;
        }

        // Add the first segment to the first octants list
        if (!octants[octantA].Contains(s))
            octants[octantA].Add(s);

        // If octA & octB are different
        if (octantA != octantB)
        {
            // We add the segment to the other list
            if (!octants[octantB].Contains(s))
                octants[octantB].Add(s);

            var diff = octantA - octantB;
            if (diff < 0)
                diff += 8;
            if (diff > 4)
                diff = 8 - diff;
            // If A & B are 4 spaces apart (very rare) it's difficult to get 
            // the octants they pass through so we just add the segment 
            // to all the octants (it's going to pass through 5 out of 8 anyway)
            // !!!! I'd like to do this right though  !!!!
            if (diff == 4)
                for (int i = 0; i < octants.Length; i++)
                {
                    if (octantA != i && octantB != i && !octants[i].Contains(s))
                        octants[i].Add(s);
                }
            else
            {
                if (diff >= 2)
                {
                    var oct = Math.Abs(diff) < 4
                        ? octantA < 7 ? octantA + 1 : 0
                        : octantA > 0 ? octantA - 1 : 7;

                    octants[oct].Add(s);
                }
                if (diff == 3)
                {
                       var oct = Math.Abs(diff) > 4
                            ? octantB < 7 ? octantB + 1 : 0
                            : octantB > 0 ? octantB - 1 : 7;
                        octants[oct].Add(s);
                }
            }
        }
    }
    return octants;
}

我现在正在使用C#,但几乎可以转换任何东西。

有人投票决定关闭这个,因为我不清楚我在问什么......要说清楚。我正在使用黑客来确定线段通过的八分圆,在某些情况下我只是忽略它并将该段添加到我的所有列表中。如果可能的话,我想收紧代码并正确使用(使用几何)。我也想避免使用atan2,因为它很慢。

1 个答案:

答案 0 :(得分:0)

八分圆由x = 0y = 0x = yx = -y行分隔。您可以通过求解相应的系统找到具有给定行的交叉点,例如a.x + b.y + c = 0

例如

a.x + b.y + c = 0
x = y

给出x = y = - c / (a + b)

一般来说,将有四个交叉点,划分五个交叉的八分圆。您可以通过查看xyx + yx - y的符号来确定交叉点属于哪个八分圆。

完整的讨论需要一些努力,但我相信你会管理。