/// <summary>
 /// Finds overlaps with another obstacle's lines.
 /// </summary>
 /// <param name="other"></param>
 public void FindOverlaps(ObstacleHitLineGroup other)
 {
     //TODO: Toggleable obstacles (like doors or bridges) should each have a independant overlap group instead
     //of using a universal overlap group here.
     //For each outside-line in this and the other group, check for overlaps. If none, also check if one is entirely
     //in the other.
 }
        private StructListStruct <int> FindOverlapsInner(int startIndex, int stopIndex, StructListStruct <int> linesToSkip, Vector surfaceNormal,
                                                         Point start, Point end, Vector firstVector, Vector lineNormal, Vector nextFirstVector, Vector nextLineNormal,
                                                         int i, ObstacleHitLineGroup otherGroup, StructListStruct <HitLineSetupOverlapData>[] setupOverlaps)
        {
            StructListStruct <int> nextLinesToSkip = default(StructListStruct <int>);
            Point secondEnd = StartPointOf(startIndex); //Initialize for j loop

            for (int j = startIndex; j < stopIndex; j++)
            {
                Point secondStart = secondEnd;
                secondEnd = otherGroup.EndPointOf(j);

                if (linesToSkip.Contains(j))
                {
                    continue;
                }

                bool  collide;
                Point intersect = KejUtils.Geometry.Geometry.LineOverlapInPlane(start, end, secondStart, secondEnd, out collide);
                if (!collide)
                {
                    continue;           //Note: Parallel lines that overlap also 'don't collide'. This is okay as long as they are handled on the lines before/after them.
                }
                Vector secondVector = secondStart.VectorTo(secondEnd);
                Vector thirdVector = secondVector;
                double prevPrevDot = lineNormal.DotProduct(secondVector);
                double prevNextDot = prevPrevDot, nextPrevDot = prevPrevDot, nextNextDot = prevPrevDot;
                bool   tiltLeft = false, nextI = false;
                if (intersect.Equals(start))
                {
                    Vector prevFirstVector;
                    if (i == 0)
                    { //Check for edge case of first line, with last line not parallel to j.
                        prevFirstVector = StartPointOf(hitLines.Count - 1).VectorTo(StartPointOf(0));
                        Vector cross = prevFirstVector.CrossProduct(secondVector);
                        if (cross.x != 0 || cross.y != 0 || cross.z != 0)
                        {
                            continue; //This will be handled later. Right now we don't want to do this.
                        }
                    }
                    else
                    {
                        Point previousStart = StartPointOf(i - 1);
                        prevFirstVector = previousStart.VectorTo(start);
                    }
                    //Previous line was parallel. Get the info for it.
                    prevPrevDot = 0;
                    prevNextDot = 0;
                    Vector prevNormal = surfaceNormal.CrossProduct(prevFirstVector);
                    tiltLeft = prevNormal.DotProduct(firstVector) > 0;

                    if (intersect.Equals(secondStart))
                    {
                        //TODO: Wait how does this case happen? I'm tempted to throw in a log statement to see if it ever happens.
                        //Backtrack second vector one index.
                        Point previousStart = otherGroup.StartPointOf(j - 1);
                        secondVector = previousStart.VectorTo(secondStart);
                        prevPrevDot  = prevNormal.DotProduct(secondVector);
                        nextPrevDot  = lineNormal.DotProduct(secondVector);
                    }
                    else if (intersect.Equals(secondEnd))
                    {
                        j++; //Skip the next line, it's known to start with this intersection and we're handling everything about it now.
                        Point nextEnd = otherGroup.EndPointOf(j);
                        thirdVector = secondEnd.VectorTo(nextEnd);
                        prevNextDot = prevNormal.DotProduct(thirdVector);
                        nextNextDot = lineNormal.DotProduct(thirdVector);
                    }
                    else
                    {
                        //Defaults are fine.
                    }
                }
                else if (intersect.Equals(end))
                {
                    //The end of line i is on line j, so the start of line i+1 will also be on line j.
                    //The intersection is being handled here in all cases, so always skip i+1 with j.
                    StructListStruct <int> .Add(ref nextLinesToSkip, j);

                    nextI = true;
                    if (intersect.Equals(secondStart))
                    {
                        //Seems safe to assume the previous lines were parallel.
                        //Backtrack second vector one index.
                        Point previousStart = otherGroup.StartPointOf(j - 1);
                        secondVector = previousStart.VectorTo(secondStart);
                        prevPrevDot  = 0;
                        nextPrevDot  = nextLineNormal.DotProduct(secondVector);
                        nextNextDot  = nextLineNormal.DotProduct(thirdVector);
                        tiltLeft     = lineNormal.DotProduct(nextFirstVector) > 0;
                    }
                    else if (intersect.Equals(secondEnd))
                    {
                        j++;                                             //Skip the next line, it's known to start with this intersection and we're handling everything about it now.
                        StructListStruct <int> .Add(ref linesToSkip, j); //Also skip i+1 with j+1

                        Point nextEnd = otherGroup.EndPointOf(j);
                        thirdVector = secondEnd.VectorTo(nextEnd);
                        prevNextDot = lineNormal.DotProduct(thirdVector);
                        nextPrevDot = nextLineNormal.DotProduct(secondVector);
                        nextNextDot = nextLineNormal.DotProduct(thirdVector);
                        tiltLeft    = lineNormal.DotProduct(nextFirstVector) > 0;
                    }
                    else
                    {
                        nextPrevDot = nextLineNormal.DotProduct(secondVector);
                        nextNextDot = nextPrevDot;
                        tiltLeft    = lineNormal.DotProduct(nextFirstVector) > 0;
                    }
                }
                else
                {
                    if (intersect.Equals(secondStart))
                    {
                        //Seems safe to assume the previous lines were parallel.
                        //Backtrack second vector one index.
                        Point previousStart = otherGroup.StartPointOf(j - 1);
                        secondVector = previousStart.VectorTo(secondStart);
                        prevPrevDot  = 0;
                        nextPrevDot  = 0;
                    }
                    else if (intersect.Equals(secondEnd))
                    {
                        j++; //Skip the next line, it's known to start with this intersection and we're handling everything about it now.
                        Point nextEnd = otherGroup.EndPointOf(j);
                        thirdVector = secondEnd.VectorTo(nextEnd);
                        prevNextDot = lineNormal.DotProduct(thirdVector);
                    }
                    else
                    {
                        //Defaults are correct for this, do nothing
                    }
                }
                int jTiltLeft = -1;
                int wasI      = (prevPrevDot < 0) ? 1 : 0;
                wasI += (prevNextDot < 0) ? 1 : 0;
                if (wasI == 1 && !thirdVector.Equals(secondVector))
                {
                    jTiltLeft = surfaceNormal.CrossProduct(secondVector).DotProduct(thirdVector) > 0 ? 1 : 0;
                    wasI     += jTiltLeft;
                }
                int isI = (nextPrevDot > 0) ? 1 : 0;
                isI += (nextNextDot > 0) ? 1 : 0;
                if (wasI == 1 && !thirdVector.Equals(secondVector))
                {
                    if (jTiltLeft == -1)
                    {
                        jTiltLeft = surfaceNormal.CrossProduct(secondVector).DotProduct(thirdVector) > 0 ? 1 : 0;
                    }
                    isI += jTiltLeft;
                }
                int wasJ = (prevPrevDot > 0) ? 1 : 0;
                wasJ += (nextPrevDot > 0) ? 1 : 0;
                wasJ += tiltLeft ? 1 : 0;
                int isJ = (prevNextDot < 0) ? 1 : 0;
                isJ += (nextNextDot < 0) ? 1 : 0;
                isJ += tiltLeft ? 1 : 0;

                if (wasI >= 2 != isI >= 2)
                {
                    HitLineSetupOverlapData newOverlap = new HitLineSetupOverlapData()
                    {
                        inside = (isI >= 2), intersect = intersect
                    };
                    StructListStruct <HitLineSetupOverlapData> .Add(ref setupOverlaps[i + (nextI ? 1 : 0)], newOverlap);
                }
                if (wasJ >= 2 != isJ >= 2)
                {
                    HitLineSetupOverlapData newOverlap = new HitLineSetupOverlapData()
                    {
                        inside = (isJ >= 2), intersect = intersect
                    };
                    StructListStruct <HitLineSetupOverlapData> .Add(ref setupOverlaps[j], newOverlap);
                }
            }
            return(nextLinesToSkip);
        }