private static List <Polygon> LinkToPolygon_Union() { //保存合并后的多边形数组 var rcNodes = new List <Vector2>(); var startV = GetLeftBottomVertex(); PolygonNode node = null; if (GetNodeIndex(lnSubject, startV) != -1) { node = lnSubject[GetNodeIndex(lnSubject, startV)]; } else if (GetNodeIndex(lnClip, startV) != -1) { node = lnClip[GetNodeIndex(lnClip, startV)]; } while (node != null) { rcNodes.Add(node.vertex); if (node.isIntersectPoint) { if (node.isOutPoint == false) //该交点为进点(跟踪主多边形边界) { if (node.isSubject == false) //当前点在副多边形中 { node = node.other; //切换到主多边形中 } } else //该交点为出点(跟踪副多边形边界) { if (node.isSubject) //当前点在主多边形中 { node = node.other; //切换到副多边形中 } } } if (node.next == null) //末尾点返回到开始点 { node = node.isSubject ? lnSubject[0] : lnClip[0]; } else { node = node.next; } //与首点相同,生成一个多边形 if (node.vertex == rcNodes[0]) { break; } } var ret = new List <Polygon> { new Polygon(rcNodes.ToArray()) }; return(ret); }
/// <summary> /// 创建polygon的nodes,最后一个node的next指向null /// </summary> /// <param name="polygon"></param> /// <param name="isIntersectPoint"></param> /// <param name="isSubject"></param> /// <returns></returns> public static List <PolygonNode> CreateNodes(Polygon polygon, bool isIntersectPoint, bool isSubject) { var nodes = new List <PolygonNode>(); PolygonNode node; for (var i = 0; i < polygon.vertexList.Count; i++) { node = new PolygonNode(polygon.vertexList[i], isIntersectPoint, isSubject); if (i > 0) { nodes[i - 1].next = node; } nodes.Add(node); } return(nodes); }
private static int IntersectPoint_Union() { var insCnt = 0; //交点数 var nSubjectCur = lnSubject[0]; PolygonNode nClipCur; Line lSubject; Line lClip; bool hasIntersectPoint; //是否有交点 while (nSubjectCur != null) //主多边形 { lSubject = nSubjectCur.next == null ? new Line(nSubjectCur.vertex, lnSubject[0].vertex) : new Line(nSubjectCur.vertex, nSubjectCur.next.vertex); //奇异情况:与裁剪多边形重合的主多边形的边不参与求交点 http://course.baidu.com/view/58a00497daef5ef7ba0d3c52.html if (IsOverLap_Union(lSubject, pClip)) { nSubjectCur = nSubjectCur.next; continue; } nClipCur = lnClip[0]; hasIntersectPoint = false; while (nClipCur != null) { lClip = nClipCur.next == null ? new Line(nClipCur.vertex, lnClip[0].vertex) : new Line(nClipCur.vertex, nClipCur.next.vertex); var lineRelation = lSubject.Intersection(lClip, out var intersectPoint); if (lineRelation == Line.LineClassification.SegmentsIntersect) //相交 { var a_on_lClip = lClip.ClassifyPoint(lSubject.pointA) == PointClassification.OnSegment; var a_index_of_lnClip = GetNodeIndex(lnClip, lSubject.pointA); var b_on_lClip = lClip.ClassifyPoint(lSubject.pointB) == PointClassification.OnSegment; var b_index_of_lnClip = GetNodeIndex(lnClip, lSubject.pointB); //主多边形边上的顶点A是在副多边形上 if (a_on_lClip && (a_index_of_lnClip == -1 || a_index_of_lnClip != -1 && lnClip[a_index_of_lnClip].isChecked == false)) { insCnt++; PolygonNode nSubjectInter = null; PolygonNode nClipInter = null; if (GetNodeIndex(lnSubject, lSubject.pointA) == -1) { nSubjectInter = new PolygonNode(lSubject.pointA, true, true); nSubjectInter.isChecked = true; lnSubject.Add(nSubjectInter); nSubjectInter.next = nSubjectCur.next; nSubjectCur.next = nSubjectInter; hasIntersectPoint = true; } else { nSubjectInter = lnSubject[GetNodeIndex(lnSubject, lSubject.pointA)]; nSubjectInter.isIntersectPoint = true; nSubjectInter.isChecked = true; } if (GetNodeIndex(lnClip, lSubject.pointA) == -1) { nClipInter = new PolygonNode(lSubject.pointA, true, false); nClipInter.isChecked = true; lnClip.Add(nClipInter); nClipInter.next = nClipCur.next; nClipCur.next = nClipInter; } else { nClipInter = lnClip[GetNodeIndex(lnClip, lSubject.pointA)]; nClipInter.isChecked = true; nClipInter.isIntersectPoint = true; } //双向引用 nSubjectInter.other = nClipInter; nClipInter.other = nSubjectInter; if (!IsOutter(lSubject, pClip)) { nSubjectInter.isOutPoint = true; nClipInter.isOutPoint = true; } else { nSubjectInter.isOutPoint = false; nClipInter.isOutPoint = false; } } //主多边形边上的顶点B是在副多边形上 if (b_on_lClip && (b_index_of_lnClip == -1 || b_index_of_lnClip != -1 && lnClip[b_index_of_lnClip].isChecked == false)) { insCnt++; PolygonNode nSubjectInter = null; PolygonNode nClipInter = null; if (GetNodeIndex(lnSubject, lSubject.pointB) == -1) { nSubjectInter = new PolygonNode(lSubject.pointB, true, true); nSubjectInter.isChecked = true; lnSubject.Add(nSubjectInter); nSubjectInter.next = nSubjectCur.next; nSubjectCur.next = nSubjectInter; hasIntersectPoint = true; } else { nSubjectInter = lnSubject[GetNodeIndex(lnSubject, lSubject.pointB)]; nSubjectInter.isIntersectPoint = true; nSubjectInter.isChecked = true; } if (GetNodeIndex(lnClip, lSubject.pointB) == -1) { nClipInter = new PolygonNode(lSubject.pointB, true, false); nClipInter.isChecked = true; lnClip.Add(nClipInter); nClipInter.next = nClipCur.next; nClipCur.next = nClipInter; } else { nClipInter = lnClip[GetNodeIndex(lnClip, lSubject.pointB)]; nClipInter.isChecked = true; nClipInter.isIntersectPoint = true; } nSubjectInter.other = nClipInter; nClipInter.other = nSubjectInter; if (!IsOutter(lSubject, pClip)) { nSubjectInter.isOutPoint = false; nClipInter.isOutPoint = false; } else { nSubjectInter.isOutPoint = true; nClipInter.isOutPoint = true; } } //交点不在顶点上的情况(主多边形的一条线段肯能跟副多边形的多条边相交) //忽略交点已在顶点列表中的 if (GetNodeIndex(lnSubject, intersectPoint.Value) == -1) { insCnt++; ///////// 插入交点 var nSubjectInter = new PolygonNode(intersectPoint.Value, true, true); nSubjectInter.isChecked = true; var nClipInter = new PolygonNode(intersectPoint.Value, true, false); nClipInter.isChecked = true; lnSubject.Add(nSubjectInter); lnClip.Add(nClipInter); //双向引用 nSubjectInter.other = nClipInter; nClipInter.other = nSubjectInter; //插入 nSubjectInter.next = nSubjectCur.next; nSubjectCur.next = nSubjectInter; nClipInter.next = nClipCur.next; nClipCur.next = nClipInter; //出点 if (lSubject.ClassifyPoint(lClip.pointB) == PointClassification.LeftSide) { nSubjectInter.isOutPoint = true; nClipInter.isOutPoint = true; } else { nSubjectInter.isOutPoint = false; nClipInter.isOutPoint = false; } hasIntersectPoint = true; //有交点 //有交点,返回重新处理 break; } } nClipCur = nClipCur.next; } //如果没有交点继续处理下一个边,否则重新处理该点与插入的交点所形成的线段 //原因:这条线段上还可能有其他的交点,注意hasIntersectPoint是只检测一次true就break,而且无法确定同一条边的交点先后顺序,所以如果有交点的时候要重新处理该点与插入的交点所形成的线段 if (hasIntersectPoint == false) { nSubjectCur = nSubjectCur.next; } } return(insCnt); }
private static int IntersectPoint_Cut() { var insCnt = 0; //交点数 var nSubjectCur = lnSubject[0]; PolygonNode nClipCur; Line lSubject; Line lClip; bool isHasIntersectPoint; //是否有交点 while (nSubjectCur != null) //主多边形 { lSubject = nSubjectCur.next == null ? new Line(nSubjectCur.vertex, lnSubject[0].vertex) : new Line(nSubjectCur.vertex, nSubjectCur.next.vertex); //奇异情况:与裁剪多边形重合的主多边形的边不参与求交点 http://course.baidu.com/view/58a00497daef5ef7ba0d3c52.html if (IsOverLap_Cut(lSubject, pClip)) { nSubjectCur = nSubjectCur.next; continue; } nClipCur = lnClip[0]; isHasIntersectPoint = false; while (nClipCur != null) { lClip = nClipCur.next == null ? new Line(nClipCur.vertex, lnClip[0].vertex) : new Line(nClipCur.vertex, nClipCur.next.vertex); var lineRelation = lSubject.Intersection(lClip, out var intersectPoint); if (lineRelation == Line.LineClassification.SegmentsIntersect) //相交 { if (lClip.ClassifyPoint(lSubject.pointA) == PointClassification.OnSegment && GetNodeIndex(lnClip, lSubject.pointA) == -1) { if (!IsOutter(lSubject, pClip)) { insCnt++; var nSubjectInter = nSubjectCur; nSubjectInter.isIntersectPoint = true; var nClipInter = new PolygonNode(lSubject.pointA, true, false); lnClip.Add(nClipInter); nClipInter.other = nSubjectInter; nSubjectInter.other = nClipInter; nClipCur = lnClip[GetNodeIndex(lnClip, lClip.pointA)]; nClipInter.next = nClipCur.next; nClipCur.next = nClipInter; nSubjectInter.isOutPoint = false; nClipInter.isOutPoint = false; } } if (lClip.ClassifyPoint(lSubject.pointB) == PointClassification.OnSegment && GetNodeIndex(lnClip, lSubject.pointB) == -1) { if (!IsOutter(lSubject, pClip)) { insCnt++; var nSubjectInter = lnSubject[GetNodeIndex(lnSubject, lSubject.pointB)]; nSubjectInter.isIntersectPoint = true; var nClipInter = new PolygonNode(lSubject.pointB, true, false); lnClip.Add(nClipInter); nSubjectInter.other = nClipInter; nClipInter.other = nSubjectInter; nClipInter.next = nClipCur.next; nClipCur.next = nClipInter; nSubjectInter.isOutPoint = true; nClipInter.isOutPoint = true; } } //忽略交点已在顶点列表中的 if (GetNodeIndex(lnSubject, intersectPoint.Value) == -1) { insCnt++; ///////// 插入交点 var nSubjectInter = new PolygonNode(intersectPoint.Value, true, true); var nClipInter = new PolygonNode(intersectPoint.Value, true, false); lnSubject.Add(nSubjectInter); lnClip.Add(nClipInter); //双向引用 nSubjectInter.other = nClipInter; nClipInter.other = nSubjectInter; //插入 nSubjectInter.next = nSubjectCur.next; nSubjectCur.next = nSubjectInter; nClipInter.next = nClipCur.next; nClipCur.next = nClipInter; //出点 if (lSubject.ClassifyPoint(lClip.pointB) == PointClassification.RightSide) { nSubjectInter.isOutPoint = true; nClipInter.isOutPoint = true; } else { nSubjectInter.isOutPoint = false; nClipInter.isOutPoint = false; } isHasIntersectPoint = true; //有交点 //有交点,返回重新处理 break; } } nClipCur = nClipCur.next; } //如果没有交点继续处理下一个边,否则重新处理该点与插入的交点所形成的线段 //原因:这条线段上还可能有其他的交点,注意hasIntersectPoint是只检测一次true就break,而且无法确定同一条边的交点先后顺序,所以如果有交点的时候要重新处理该点与插入的交点所形成的线段 if (isHasIntersectPoint == false) { nSubjectCur = nSubjectCur.next; } } return(insCnt); }