/// <summary> /// <para>获取otherVertsPloy相对于mainPoly的覆盖关系:(只在主多边形上找投影轴, 并且不考虑多边形中空的情况)</para> /// <para>[ FullOverlap ]: otherVertsPloy完全重叠到mainPloy</para> /// <para>[ PartOverlay ]:otherVertsPloy部分重叠mainPloy</para> /// <para>[ NotOverlay ]:两个多边形互不重叠</para> /// </summary> /// <param name="mainPoly"></param> /// <param name="otherVertsPloy"></param> /// <returns> /// FullOverlap: otherVertsPloy完全重叠到mainPloy /// PartOverlay:otherVertsPloy部分重叠mainPloy /// NotOverlay:两个多边形互不重叠 /// </returns> public OverlapRelation GetOverlapRelation(Poly mainPoly, Vector3d[] otherVertsPloy) { double[] range; PolySide[] sides = mainPoly.sidesList[0]; OverlapRelation relation = OverlapRelation.FullOverlap; OverlapRelation tmpRelation; for (int i = 0; i < sides.Length; i++) { range = ProjectPoly(sides[i].vertDir, otherVertsPloy); tmpRelation = _OverlapRelation(range[0], range[1], mainPoly.projRange[i].min, mainPoly.projRange[i].max); if (tmpRelation == OverlapRelation.PartOverlay) { relation = OverlapRelation.PartOverlay; } else if (tmpRelation == OverlapRelation.FullOverlap && relation != OverlapRelation.PartOverlay) { relation = OverlapRelation.FullOverlap; } else if (tmpRelation == OverlapRelation.NotOverlay) { return(OverlapRelation.NotOverlay); } } return(relation); }
/// <summary> /// 排序多边形边上的交点顺序,按距离起始点 /// </summary> /// <param name="poly"></param> void SortPolyCrossPointInfo(Poly poly) { List <PolySide[]> sidesList = poly.sidesList; PolySide[] sides; List <CrossPointInfo> crossPtInfoList; CrossPointInfo crossPtInfo; for (int i = 0; i < sidesList.Count; i++) { sides = sidesList[i]; for (int j = 0; j < sides.Length; j++) { crossPtInfoList = sides[j].crossPointInfoList; if (crossPtInfoList == null) { continue; } crossPtInfoList.Sort(cmp); for (int k = 0; k < crossPtInfoList.Count; k++) { crossPtInfoList[k].pointIdx = k; crossPtInfo = crossPtInfoList[k].GetCrossSideCrossPointInfo(); if (crossPtInfo != null) { crossPtInfo.crossSidePointIdx = k; } } } } }
public Poly Copy() { Poly poly = new Poly(); poly.faceNormal = faceNormal; for (int i = 0; i < sidesList.Count; i++) { PolySide[] polySides = new PolySide[sidesList[i].Length]; for (int j = 0; j < sidesList[i].Length; j++) { polySides[j] = sidesList[i][j].Copy(); } poly.sidesList.Add(polySides); } for (int i = 0; i < sidesList.Count; i++) { Vector3d[] verts = new Vector3d[vertexsList[i].Length]; for (int j = 0; j < sidesList[i].Length; j++) { verts[j] = vertexsList[i][j]; } poly.vertexsList.Add(verts); } return(poly); }
void AdjustPolyEndPointInfo(Poly poly) { CrossPointInfo crossPtInfo; List <PolySide[]> sidesList = poly.sidesList; for (int i = 0; i < sidesList.Count; i++) { PolySide[] sides = sidesList[i]; for (int j = 0; j < sides.Length; j++) { crossPtInfo = sides[j].crossPointInfoList[0]; if (j == 0) { crossPtInfo.crossSide = sides[sides.Length - 1]; } else { crossPtInfo.crossSide = sides[j - 1]; } crossPtInfo.crossSidePointIdx = crossPtInfo.crossSide.crossPointInfoList.Count - 1; crossPtInfo = sides[j].crossPointInfoList[sides[j].crossPointInfoList.Count - 1]; if (j == sides.Length - 1) { crossPtInfo.crossSide = sides[0]; } else { crossPtInfo.crossSide = sides[j + 1]; } crossPtInfo.crossSidePointIdx = 0; } } }
bool HavCrossPoint(Poly poly, PolySide sideAB, IgnoreSideInfo[] ignoreSideInfos) { int result; Vector3d pt; for (int i = 0; i < poly.sidesList.Count; i++) { PolySide[] sides = poly.sidesList[i]; for (int j = 0; j < sides.Length; j++) { if (InIgnoreSides(i, j, ignoreSideInfos)) { continue; } //求解ab线段和多边形边sides[j]的交点 result = geoAlgor.SolvePolySideCrossPoint2D(sides[j], sideAB, out pt); if (result == 1) //存在交点 { return(true); } } } return(false); }
public void Union(Poly polyA, Poly polyB) { this.polyA = polyA.Copy(); this.polyB = polyB.Copy(); AdjustPolyPos(this.polyB); CreatePolysCrossPointInfoGroup(); UnionOp(); }
/// <summary> /// 判断点pt是否在多边形中 /// </summary> /// <param name="poly">多边形</param> /// <param name="polyFaceNormal"></param> /// <param name="pt"></param> /// <returns></returns> public bool IsInsidePolyEx(Poly poly, Vector3d pt, PloySideType checkSideType = PloySideType.Allside) { PolySide[] polySides = poly.sidesList[0]; Vector3d n = Vector3d.Cross(pt - polySides[0].startpos, polySides[0].dir); if (!IsZero(n) || !IsParallel(n, poly.faceNormal)) { return(false); } return(IsInsidePoly(poly, pt, checkSideType)); }
void RestorePolyPos(Poly poly) { List <PolySide[]> sidesList = poly.sidesList; for (int i = 0; i < sidesList.Count; i++) { PolySide[] sides = sidesList[i]; for (int j = 0; j < sides.Length; j++) { sides[j].startpos -= offsetValue; } } }
/// <summary> /// 判断点pointMustInPloyPlane是否在多边形中, /// pointMustInPloyPlane必须在多边形的同一平面中,但不一定在多边形中 /// </summary> /// <param name="polySides">多边形中所有点共面</param> /// <param name="pointMustInPloyPlane"></param> /// <returns></returns> public bool IsInsidePoly(Poly poly, Vector3d pointMustInPloyPlane, PloySideType checkSideType = PloySideType.Allside) { PolySide[] polySides; List <PolySide[]> polySidesList = poly.sidesList; Vector3d pt = pointMustInPloyPlane; Vector3d polyFaceNormal = poly.faceNormal; //判断从点引出的平行于sides[0]方向的正向射线是否与其它边相交 Vector3d n = polySidesList[0][0].startpos - pt; int crossPtCount = 0; Vector3d crossPt; PolySide polySide2 = new PolySide(); polySide2.startpos = pt; polySide2.dir = n; polySide2.step = 1000000; for (int j = 0; j < polySidesList.Count; j++) { if (checkSideType == PloySideType.Outside) { if (j == 1) { break; } } else if (checkSideType == PloySideType.Inside) { if (j == 0) { continue; } } polySides = polySidesList[j]; for (int i = 0; i < polySides.Length; i++) { crossPtCount += SolvePolySideCrossPoint(polySides[i], polySide2, polyFaceNormal, true, out crossPt); } } //判断是偶数个交点,还是奇数个交点 if (crossPtCount % 2 == 0) { return(false); } return(true); }
/// <summary> /// 计算多边形自身投影轴的范围 /// </summary> /// <param name="poly"></param> public void CreatePolySelfProjectAxisRange(Poly poly) { double[] range; PolySide[] sides = poly.sidesList[0]; Range[] ranges = new Range[sides.Length]; for (int i = 0; i < sides.Length; i++) { range = ProjectPoly(sides[i].vertDir, poly.vertexsList[0]); ranges[i].min = range[0]; ranges[i].max = range[1]; } poly.projRange = ranges; }
LinkedList <Vector3d> CreatePolyVertToList(Poly poly) { if (poly == null) { return(null); } LinkedList <Vector3d> polyVertList = new LinkedList <Vector3d>(); Vector3d[] triPts = poly.vertexsList[0]; for (int i = 0; i < triPts.Length; i++) { polyVertList.AddLast(triPts[i]); } return(polyVertList); }
/// <summary> /// 判断两个多边形是否互相重叠(只在主多边形上找投影轴, 并且不考虑多边形中空的情况) /// </summary> /// <param name="mainPoly">主多边形</param> /// <param name="otherVertsPloy">需要判断的多边形点</param> /// <returns></returns> public bool IsOverlap(Poly mainPoly, Vector3d[] otherVertsPloy) { double[] range; PolySide[] sides = mainPoly.sidesList[0]; for (int i = 0; i < sides.Length; i++) { range = ProjectPoly(sides[i].vertDir, otherVertsPloy); if (!OverlapRange(range[0], range[1], mainPoly.projRange[i].min, mainPoly.projRange[i].max)) { return(false); } } return(true); }
void CreateInoutTypeVertesxToResult(Poly polya, Poly polyb) { for (int i = 0; i < polya.vertexsList.Count; i++) { resultPolyVertsList.Add(polya.vertexsList[i]); } for (int i = 0; i < polyb.vertexsList.Count; i++) { int len = polyb.vertexsList[i].Length; Vector3d[] verts = new Vector3d[len]; for (int j = 0; j < len; j++) { verts[j] = polyb.vertexsList[i][len - i - 1]; } resultPolyVertsList.Add(verts); } }
/// <summary> /// 生成多边形交点的进出点类型 /// </summary> void CreatePolysCrossPointsInOutType(Poly polyA, Poly polyB) { List <PolySide[]> sidesListA = polyA.sidesList; int inoutType = 0; List <CrossPointInfo> cpinfoList; CrossPointInfo cpinfo; for (int i = 0; i < sidesListA.Count; i++) { PolySide[] sidesA = sidesListA[i]; if (geoAlgor.IsInsidePoly(polyB, sidesA[0].startpos)) { inoutType = 1; } else { inoutType = 0; } cpinfoList = sidesA[0].crossPointInfoList; cpinfoList[0].inoutType = inoutType; for (int j = 0; j < sidesA.Length; j++) { cpinfoList = sidesA[j].crossPointInfoList; for (int k = 1; k < cpinfoList.Count; k++) { if (k == cpinfoList.Count - 1) { cpinfoList[k].inoutType = cpinfoList[k - 1].inoutType; cpinfo = cpinfoList[k].GetCrossSideCrossPointInfo(); cpinfo.inoutType = cpinfoList[k].inoutType; } else { cpinfoList[k].inoutType = 1 - cpinfoList[k - 1].inoutType; } } } } }
void AdjustPolyPos(Poly poly) { Vector3d dir1 = poly.sidesList[0][0].dir; Vector3d dir2 = poly.sidesList[0][1].dir; Vector3d dir3 = poly.sidesList[0][2].dir; float[] scales = CreateRandomScales(); offsetValue = dir1 * scales[0] + dir2 * scales[1] + dir3 * scales[2]; List <PolySide[]> sidesList = poly.sidesList; for (int i = 0; i < sidesList.Count; i++) { PolySide[] sides = sidesList[i]; for (int j = 0; j < sides.Length; j++) { sides[j].startpos += offsetValue; } } }
/// <summary> /// 为多边形生成端点的交点信息 /// </summary> /// <param name="poly"></param> void CreatePolyEndPointInfo(Poly poly) { CrossPointInfo crossPtInfo; List <PolySide[]> sidesList = poly.sidesList; for (int i = 0; i < sidesList.Count; i++) { PolySide[] sides = sidesList[i]; for (int j = 0; j < sides.Length; j++) { if (sides[j].crossPointInfoList == null) { sides[j].crossPointInfoList = new List <CrossPointInfo>(); } sides[j].crossPointInfoList = new List <CrossPointInfo>(); crossPtInfo = new CrossPointInfo(); crossPtInfo.type = PointType.EndPoint; crossPtInfo.selfSide = sides[j]; crossPtInfo.crossSide = null; crossPtInfo.pt = sides[j].startpos; crossPtInfo.pointIdx = 0; crossPtInfo.crossSidePointIdx = 1; crossPtInfo.dist = 0 - 0.0001f; sides[j].crossPointInfoList.Add(crossPtInfo); crossPtInfo = new CrossPointInfo(); crossPtInfo.type = PointType.EndPoint; crossPtInfo.selfSide = sides[j]; crossPtInfo.crossSide = null; crossPtInfo.pt = sides[j].startpos + sides[j].dir * sides[j].step; crossPtInfo.pointIdx = 1; crossPtInfo.crossSidePointIdx = 0; crossPtInfo.dist = sides[j].step + 0.0001f; sides[j].crossPointInfoList.Add(crossPtInfo); } } }
/// <summary> /// 生成多边形 /// </summary> /// <param name="vertexs"></param> /// <returns></returns> public Poly CreatePoly(List <Vector3d[]> polyVertexsList, Vector3d?faceNormal) { Poly poly = new Poly(); poly.vertexsList = polyVertexsList; if (faceNormal == null) { Vector3d[] polyVertexs = polyVertexsList[0]; Vector3d vec1 = polyVertexs[1] - polyVertexs[0]; Vector3d vec2 = polyVertexs[2] - polyVertexs[0]; poly.faceNormal = Vector3d.Cross(vec1, vec2); poly.faceNormal.Normalize(); } else { poly.faceNormal = faceNormal.Value; } poly.sidesList = CreatePolySidesList(poly.vertexsList, poly.faceNormal); return(poly); }
void AddIgnoreSideInfos(Poly poly, int ring, int vertIdx, List <IgnoreSideInfo> ignoreSideInfos) { IgnoreSideInfo ignoreSideInfo; int otherSideIdx; if (vertIdx == 0) { otherSideIdx = poly.sidesList[ring].Length - 1; } else { otherSideIdx = vertIdx - 1; } ignoreSideInfo = new IgnoreSideInfo() { ringIdx = ring, sideIdx1 = vertIdx, sideIdx2 = otherSideIdx }; ignoreSideInfos.Add(ignoreSideInfo); }
bool HavOverlayPoint(Poly poly, Vector3d vert) { Vector3d[] vertexs; int count = 0; for (int i = 0; i < poly.vertexsList.Count; i++) { vertexs = poly.vertexsList[i]; for (int j = 0; j < vertexs.Length; j++) { if (geoAlgor.IsEqual(vertexs[j], vert) == false) { continue; } count++; if (count == 2) { return(true); } } } return(false); }
void CreatePoly() { poly = geoAlgo.CreatePoly(vertexs, triFaceNormal); geoAlgo.CreatePolySelfProjectAxisRange(poly); }
void CreatePolys(Vector3d[] polyVertsA, Vector3d[] polyVertsB) { polyA = geoAlgor.CreatePoly(polyVertsA, Vector3d.zero); polyB = geoAlgor.CreatePoly(polyVertsB, Vector3d.zero); AdjustPolyPos(polyB); }
public List <Vector3d[]> Split(Poly poly) { LinkedList <Vector3d> polyVertList = CreatePolyVertToList(poly); return(Split(polyVertList, poly.faceNormal)); }
/// <summary> /// 生成去除一个内环后的多边形 /// </summary> /// <param name="poly">原始多边形</param> /// <param name="ringIdx">内环在原始多边形中的编号</param> /// <param name="ringVertexIdx">内环分切点编号</param> /// <param name="outVertexIdx">外环分切点编号</param> /// <param name="endLinkSide">连接线段</param> /// <returns></returns> Poly CreatePolyByRemoveRing( Poly poly, int ringIdx, int ringSplitVertIdx, int outSplitVertIdx, PolySide endLinkSide) { List <Vector3d> resultPolyVertexList = new List <Vector3d>(); List <PolySide> resultPolySideList = new List <PolySide>(); Vector3d outVert = poly.vertexsList[0][outSplitVertIdx]; Vector3d startVert = poly.vertexsList[ringIdx][ringSplitVertIdx]; for (int i = outSplitVertIdx; i < poly.vertexsList[0].Length; i++) { resultPolyVertexList.Add(poly.vertexsList[0][i]); } for (int i = 0; i <= outSplitVertIdx; i++) { resultPolyVertexList.Add(poly.vertexsList[0][i]); } for (int i = ringSplitVertIdx; i < poly.vertexsList[ringIdx].Length; i++) { resultPolyVertexList.Add(poly.vertexsList[ringIdx][i]); } for (int i = 0; i <= ringSplitVertIdx; i++) { resultPolyVertexList.Add(poly.vertexsList[ringIdx][i]); } // for (int i = outSplitVertIdx; i < poly.sidesList[0].Length; i++) { resultPolySideList.Add(poly.sidesList[0][i]); } for (int i = 0; i < outSplitVertIdx; i++) { resultPolySideList.Add(poly.sidesList[0][i]); } PolySide linkSide = geoAlgor.CreatePolySide(outVert, startVert); resultPolySideList.Add(linkSide); for (int i = ringSplitVertIdx; i < poly.sidesList[ringIdx].Length; i++) { resultPolySideList.Add(poly.sidesList[ringIdx][i]); } for (int i = 0; i < ringSplitVertIdx; i++) { resultPolySideList.Add(poly.sidesList[ringIdx][i]); } resultPolySideList.Add(endLinkSide); // Poly resultPoly = new Poly(); resultPoly.sidesList.Add(resultPolySideList.ToArray()); for (int i = 1; i < poly.sidesList.Count; i++) { if (i == ringIdx) { continue; } resultPoly.sidesList.Add(poly.sidesList[i]); } // resultPoly.vertexsList.Add(resultPolyVertexList.ToArray()); for (int i = 1; i < poly.vertexsList.Count; i++) { if (i == ringIdx) { continue; } resultPoly.vertexsList.Add(poly.vertexsList[i]); } resultPoly.faceNormal = poly.faceNormal; return(resultPoly); }
/// <summary> /// 切割为简单多边形 /// </summary> /// <param name="poly"></param> /// <returns></returns> public Poly ConvertToSimplePoly2D(Poly poly) { List <IgnoreSideInfo> ignoreSideInfos = new List <IgnoreSideInfo>(); Vector3d startVertA; Vector3d endVertA; PolySide sideAB; Vector3d[] outsideVertexs; Vector3d[] insideVertexs; while (true) { //判断是否存在内环多边形,当不存在内环时,结束算法,返回最后生成的多边形 if (poly.vertexsList.Count <= 1) { return(poly); } outsideVertexs = poly.vertexsList[0]; for (int i = 1; i < poly.vertexsList.Count; i++) { insideVertexs = poly.vertexsList[i]; for (int j = 1; j < insideVertexs.Length; j++) { ignoreSideInfos.Clear(); startVertA = insideVertexs[j]; AddIgnoreSideInfos(poly, i, j, ignoreSideInfos); for (int k = 0; k < outsideVertexs.Length; k++) { endVertA = outsideVertexs[k]; if (ignoreSideInfos.Count == 2) { ignoreSideInfos.RemoveAt(1); } AddIgnoreSideInfos(poly, 0, k, ignoreSideInfos); if (HavOverlayPoint(poly, endVertA)) { continue; } sideAB = geoAlgor.CreatePolySide(startVertA, endVertA); if (HavCrossPoint(poly, sideAB, ignoreSideInfos.ToArray())) { continue; } poly = CreatePolyByRemoveRing(poly, i, j, k, sideAB); i = poly.vertexsList.Count; j = insideVertexs.Length; break; } } if (i == 0) { break; } else if (i == poly.vertexsList.Count - 1) { i = -1; } } } }
void CreateProjectionToFloorPoly() { polyProjectionFloor = geoAlgo.CreatePoly(vertexsProjectionFloor, floorGridNormal); geoAlgo.CreatePolySelfProjectAxisRange(polyProjectionFloor); }