Пример #1
0
        /// <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;
                        }
                    }
                }
            }
        }
Пример #3
0
        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();
 }
Пример #7
0
        /// <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;
                }
            }
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
        /// <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);
        }
Пример #12
0
        /// <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);
                }
            }
        }
Пример #17
0
        /// <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);
        }
Пример #20
0
 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;
                    }
                }
            }
        }
Пример #25
0
 void CreateProjectionToFloorPoly()
 {
     polyProjectionFloor = geoAlgo.CreatePoly(vertexsProjectionFloor, floorGridNormal);
     geoAlgo.CreatePolySelfProjectAxisRange(polyProjectionFloor);
 }