去 i-1 时如何处理循环

How to handle loops when going i-1

我有一个关于在 C# 中循环的一般性问题,尤其是在使用列表时。

我想实现一个简单的多边形切耳算法。 这是算法:

(来源:http://www.diva-portal.org/smash/get/diva2:330344/FULLTEXT02 , 第 6 页)

我已经实现了寻找耳塞。但问题是我必须访问列表的 i-1 或有时甚至是 i-2 元素。我的解决方法是在列表顶部添加最后一个元素,在列表末尾添加第一个元素。

但是当它进入下一步时,当我必须从多边形中删除一些点以通过算法走得更远时,这种方法一点也不好。所以问题是当我在开始工作时尝试访问多边形末端的元素时 =) 我希望这是有道理的。

这里有一个片段,让你知道我在说什么:

// suppose that i = 0 at the first step and polygonPoints is List<Vector>
Vector pi = new Vector(polygonPoints[i - 1]);
Vector pj = new Vector(polygonPoints[i]);
Vector pk = new Vector(polygonPoints[i + 1]);

// create line between i-1 and i+1
Line diagonal = new Line(pi,pk);

如有任何建议,我将不胜感激。 提前致谢。

希望我理解正确:你的问题是计算节点列表末尾的邻居索引,对吗?

如果是这样,您为什么不使用简单的模函数来计算索引:

int mod(int k, int x)
{
    return ((k % x) + x) % x;
}
//...
polygonPoints[mod(i + n, polygonPoints.length)]

其中 n 是您的偏移量。

这意味着例如对于包含 10 个元素的多边形点列表,i = 9n = 1 即:

mod((9 + 1), 10) = 0

特别是,索引 9 处节点的下一个邻居位于索引 0

对于i = 0n = -1

mod((0 - 1), 10) = 9

这意味着,索引 0 处节点的前一个节点位于索引位置 9

您还可以在集合上创建一个 decorator。 然后你可以定义indexer property来处理越界索引。

这样你就不用一直调用mod,它会在索引器中处理。您必须有一个支持索引或 IndexOf 的集合,例如 List.

using System;
using System.Collections;
using System.Collections.Generic;

class Program
{
    private static void Main(string[] args)
    {
        var list = new List<int> { 1, 2, 3, 4, 5 };
        var decoratedList = new OverindexableListDecorator<int>(list);

        Console.WriteLine("-1st element is: {0}", decoratedList[-1]);
        Console.WriteLine("Element at index 3 is: {0}", decoratedList[3]);
        Console.WriteLine("6th element is: {0}", decoratedList[6]);

        Console.ReadKey();
    }
}

class OverindexableListDecorator<T> : IList<T>
{
    private readonly IList<T> store;

    public OverindexableListDecorator(IList<T> collectionToWrap)
    {
        this.store = collectionToWrap;
    }

    public T this[int index]
    {
        get
        {
            int actualIndex = IndexModuloCount(index);
            return store[actualIndex];
        }
        set
        {
            int actualIndex = IndexModuloCount(index);
            store[actualIndex] = value;
        }
    }

    public void RemoveAt(int index)
    {
        var actualIndex = IndexModuloCount(index);
        store.RemoveAt(index);
    }

    public void Insert(int index, T item)
    {
        var actualIndex = IndexModuloCount(index);
        store.Insert(actualIndex, item);
    }

    private int IndexModuloCount(int i)
    {
        int count = this.Count;
        return ((i % count) + count) % count;
    }

    #region Delegate calls
    public IEnumerator<T> GetEnumerator()
    {
        return store.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Add(T item)
    {
        store.Add(item);
    }

    public void Clear()
    {
        store.Clear();
    }

    public bool Contains(T item)
    {
        return store.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        store.CopyTo(array, arrayIndex);
    }

    public bool Remove(T item)
    {
        return store.Remove(item);
    }

    public int Count
    {
        get { return store.Count; }
    }


    public bool IsReadOnly
    {
        get { return store.IsReadOnly; }
    }

    public int IndexOf(T item)
    {
        return store.IndexOf(item);
    }

    #endregion
}