/// <summary> /// 对vertices组成的多边形三角形化. /// <para>earTips为当前的耳朵的索引.</para> static List<Vertex> DoTriangulate(ArrayLinkedList<EarVertex> vertices, ArrayLinkedList<int> earTips) { // N边行, 形成N-2个三角形, 共3*(N-2)个顶点. List<Vertex> answer = new List<Vertex>((vertices.Count - 2) * 3); // 被移除的耳朵. EarVertex[] removedEars = new EarVertex[2]; int removedEarCount = 0; // 需要被移除的耳朵的在earTips中的索引. int earTipIndex = -1; for (var e = earTips.GetEnumerator(); e.MoveNext(); ) { if (earTipIndex >= 0) { earTips.RemoveAt(earTipIndex); } earTipIndex = e.CurrentIndex; // 需要移除的耳朵的在vertices中的索引. int earTipVertexIndex = earTips[earTipIndex]; // 需要移除的耳朵节点. EarVertex earTipVertex = vertices[earTipVertexIndex]; // 耳朵节点的上一个节点. int prevIndex = vertices.PrevIndex(earTipVertexIndex); EarVertex prevVertex = vertices.PrevValue(earTipVertexIndex); // 耳朵节点的下一个节点. int nextIndex = vertices.NextIndex(earTipVertexIndex); EarVertex nextVertex = vertices.NextValue(earTipVertexIndex); // 构成新的三角形. answer.Add(prevVertex.vertex); answer.Add(earTipVertex.vertex); answer.Add(nextVertex.vertex); // 以该节点为耳尖的耳朵已被"切掉", 移除这个节点. vertices.RemoveAt(earTipVertexIndex); // 更新该节点的上节点的状态. int state = UpdateEarVertexState(vertices, prevIndex); // 加入新的耳朵. if (state > 0) { prevVertex.earListIndex = earTips.Add(prevIndex); } // 收集之前是, 而现在不再是耳朵的节点. else if (state < 0) { removedEars[removedEarCount++] = prevVertex; } // 更新该节点的下节点的状态. state = UpdateEarVertexState(vertices, nextIndex); if (state > 0) { nextVertex.earListIndex = earTips.Add(nextIndex); } else if (state < 0) { removedEars[removedEarCount++] = nextVertex; } // 在earTips中移除之前是, 现在不是耳朵的节点. for (int i = 0; i < removedEarCount; ++i) { Utility.Verify(removedEars[i].earListIndex >= 0); earTips.RemoveAt(removedEars[i].earListIndex); removedEars[i].earListIndex = -1; } removedEarCount = 0; } // 移除最后一个耳朵, 清空earTips. if (earTipIndex >= 0) { earTips.RemoveAt(earTipIndex); } return answer; }
/// <summary> /// 检查vertices[index]的内角, 是否为优角. /// </summary> /// <param name="vertices"></param> /// <param name="index"></param> /// <returns></returns> static bool CheckIsReflex(ArrayLinkedList<EarVertex> vertices, int index) { Vertex current = vertices[index].vertex; Vertex prev = vertices.PrevValue(index).vertex; Vertex next = vertices.NextValue(index).vertex; return next.Position.cross2(prev.Position, current.Position) < 0f; }