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 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); }
/// <summary> /// 求解多边形边的交点, /// 是否比较边的端点(比较边的端点一般用于点是否在多边形中的判断) /// </summary> /// <param name="polySide1">多边形的一条边</param> /// <param name="polySide2">多边形的一条边</param> /// <param name="isCmpSideEndPoint">是否比较边的端点(比较边的端点一般用于点是否在多边形中的判断)</param> /// <param name="crossPt">两条边的交点</param> /// <returns>返回值为 1: 有1个交点, 0:没有交点</returns> public int SolvePolySideCrossPoint2D(PolySide polySide1, PolySide polySide2, bool isCmpSideEndPoint, out Vector3d crossPt) { Vector3d m = new Vector3d(polySide1.dir.z, 0, -polySide1.dir.x); bool isHavCrossPt = SolveCrossPoint2D(polySide2.startpos, polySide2.dir, polySide1.startpos, m, out crossPt); //两条边互相平行 if (!isHavCrossPt) { return(0); } double step; Vector3d crossPtToPtVec = crossPt - polySide2.startpos; CmpParallelVecDir(crossPtToPtVec, polySide2.dir, out step); //交点crossPt不在polySide2边的范围内 if (step < 0 || step > polySide2.step + esp) { return(0); } crossPtToPtVec = crossPt - polySide1.startpos; //交点与端点重合 if (IsZero(crossPtToPtVec)) { if (isCmpSideEndPoint) { Vector3d sideEndPt = polySide1.startpos + polySide1.dir * polySide1.step; double v = Cross2D(sideEndPt - polySide2.startpos, polySide2.dir); return(v < 0 ? 1 : 0); } return(1); } else if (IsEqual(crossPtToPtVec, polySide1.dir * polySide1.step)) { if (isCmpSideEndPoint) { double v = Cross2D(polySide1.startpos - polySide2.startpos, polySide2.dir); return(v < 0 ? 1 : 0); } return(1); } CmpParallelVecDir(crossPtToPtVec, polySide1.dir, out step); //交点crossPt不在polySide1边的范围内 if (step < 0 || step > polySide1.step + esp) { return(0); } return(1); }
/// <summary> /// 生成PolySide /// </summary> /// <param name="startVertex"></param> /// <param name="endVertex"></param> /// <returns></returns> public PolySide CreatePolySide(Vector3d startVertex, Vector3d endVertex) { PolySide side = new PolySide(); side.startpos = startVertex; side.dir = endVertex - startVertex; side.step = side.dir.magnitude; side.dir /= side.step; return(side); }
/// <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> /// 生成基础数据的PolySide组 /// </summary> /// <param name="polyVertexs"></param> /// <returns></returns> public PolySide[] CreatePolySides(Vector3d[] polyVertexs) { PolySide[] sides = new PolySide[polyVertexs.Length]; for (int i = 0; i < polyVertexs.Length; i++) { if (i == polyVertexs.Length - 1) { sides[i] = CreatePolySide(polyVertexs[i], polyVertexs[0]); } else { sides[i] = CreatePolySide(polyVertexs[i], polyVertexs[i + 1]); } } return(sides); }
public PolySide Copy() { PolySide polySide = new PolySide(); polySide.startpos = startpos; polySide.dir = dir; polySide.step = step; polySide.vertDir = vertDir; if (crossPointInfoList != null) { polySide.crossPointInfoList = new List <CrossPointInfo>(); for (int i = 0; i < crossPointInfoList.Count; i++) { polySide.crossPointInfoList[i] = crossPointInfoList[i].Copy(); } } return(polySide); }
/// <summary> /// 求解多边形边的交点, /// 是否比较边的端点(比较边的端点一般用于点是否在多边形中的判断) /// </summary> /// <param name="polySide1">多边形的一条边</param> /// <param name="polySide2">多边形的一条边</param> /// <param name="polyFaceNormal">多边形面向法线</param> /// <param name="isCmpSideEndPoint">是否比较边的端点(比较边的端点一般用于点是否在多边形中的判断)</param> /// <param name="crossPt">两条边的交点</param> /// <returns>返回值为 1: 有1个交点, 0:没有交点</returns> public int SolvePolySideCrossPoint( PolySide polySide1, PolySide polySide2, Vector3d polyFaceNormal, bool isCmpSideEndPoint, out Vector3d crossPt) { //m为新的平面的法向,要求m和 polySide1.dir互相垂直,同时m不能与poly的法向平行 //既由m确认的平面不能是poly的平面 Vector3d m = Vector3d.Cross(polySide1.dir, polyFaceNormal); bool isHavCrossPt = SolveCrossPoint(polySide2.startpos, polySide2.dir, polySide1.startpos, m, out crossPt); //两条边互相平行 if (!isHavCrossPt) { return(0); } double step; Vector3d crossPtToPtVec = crossPt - polySide2.startpos; CmpParallelVecDir(crossPtToPtVec, polySide2.dir, out step); //交点crossPt不在polySide2边的范围内 if (step < 0 || step > polySide2.step + esp) { return(0); } crossPtToPtVec = crossPt - polySide1.startpos; //交点与端点重合 if (IsZero(crossPtToPtVec)) { if (isCmpSideEndPoint) { Vector3d sideEndPt = polySide1.startpos + polySide1.dir * polySide1.step; Vector3d v = Vector3d.Cross(sideEndPt - polySide2.startpos, polySide2.dir); if (CmpParallelVecDir(v, polyFaceNormal, out step) != 1) { return(1); } return(0); } return(1); } else if (IsEqual(crossPtToPtVec, polySide1.dir * polySide1.step)) { if (isCmpSideEndPoint) { Vector3d v = Vector3d.Cross(polySide1.startpos - polySide2.startpos, polySide2.dir); if (CmpParallelVecDir(v, polyFaceNormal, out step) != 1) { return(1); } return(0); } return(1); } CmpParallelVecDir(crossPtToPtVec, polySide1.dir, out step); //交点crossPt不在polySide1边的范围内 if (step < 0 || step > polySide1.step + esp) { return(0); } return(1); }
/// <summary> /// 求解多边形边的交点(此功能不比较边的方向,一般比较边的方向用于点是否在多边形中的判断) /// </summary> /// <param name="polySide1">多边形的一条边</param> /// <param name="polySide2">多边形的一条边</param> /// <param name="polyFaceNormal">多边形面向法线</param> /// <param name="crossPt">输出射线和边的交点</param> /// <returns>返回值为 1: 有1个交点, 0:没有交点</returns> public int SolvePolySideCrossPoint(PolySide polySide1, PolySide polySide2, Vector3d polyFaceNormal, out Vector3d crossPt) { return(SolvePolySideCrossPoint(polySide1, polySide2, polyFaceNormal, false, out crossPt)); }
/// <summary> /// 求解多边形边的交点(此功能不比较边的方向,一般比较边的方向用于点是否在多边形中的判断) /// </summary> /// <param name="polySide1">多边形的一条边</param> /// <param name="polySide2">多边形的一条边</param> /// <param name="polyFaceNormal">多边形面向法线</param> /// <param name="crossPt">输出射线和边的交点</param> /// <returns>返回值为 1: 有1个交点, 0:没有交点</returns> public int SolvePolySideCrossPoint2D(PolySide polySide1, PolySide polySide2, out Vector3d crossPt) { return(SolvePolySideCrossPoint2D(polySide1, polySide2, false, out crossPt)); }
/// <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); }