Beispiel #1
0
 /// Разделить текущее ребро на два, очистив при этом инфу о текущем ребре
 internal graphLine[] Split(graphPoint graphPoint)
 {
     var edge1 = new graphLine { a = a, b = b};
      var edge2 = new graphLine { a = a, b = b };
      edge1.p1 = p1;
      edge1.p2 = graphPoint;
      edge2.p1 = graphPoint;
      edge2.p2 = p2;
      p1 = null;
      p2 = null;
      edge1.aMain = aMain;
      edge2.aMain = aMain;
      return new[] { edge1, edge2 };
 }
Beispiel #2
0
        public static graphLine[] calculateLines(Vector3[] aPoints, Vector3[] bPoints)
        {
            //Create triangles and reverse if unclockwise
             var aPoints2D = getClockwisePoint2D(aPoints);
             var bPoints2D = getClockwisePoint2D(bPoints);
             //Create edges
             var aEdges = new List<graphLine>(aPoints.Length);
             for (int i = 0; i < aPoints2D.Length; i++)
             {
                 var edge = new graphLine { aMain = true, a = true, p1 = aPoints2D[i], p2 = aPoints2D[(i + 1) % aPoints2D.Length] };
                 aEdges.Add(edge);
             }
             var bEdges = new List<graphLine>(bPoints.Length);
             for (int i = 0; i < bPoints2D.Length; i++)
             {
                 var edge = new graphLine { aMain = false, b = true, p1 = bPoints2D[i], p2 = bPoints2D[(i + 1) % bPoints2D.Length] };
                 bEdges.Add(edge);
             }
             //Phase 1: Split & cross
             int aFirstCrossIndex = -1, bFirstCrossIndex = -1;
             for (int i1 = 0; i1 < aEdges.Count; i1++)
             {
                 for (int i2 = 0; i2 < bEdges.Count; i2++)
                 {
                     graphLine[] aOut, bOut;
                     if (_detectIntersectionsIfNeed(aEdges[i1], bEdges[i2], out aOut, out bOut))
                     {
                         aEdges.RemoveAt(i1);
                         bEdges.RemoveAt(i2);
                         aEdges.InsertRange(i1, aOut);
                         bEdges.InsertRange(i2, bOut);
                         aFirstCrossIndex = i1 + 1;
                         bFirstCrossIndex = i2 + 1;
                         i2++;
                     }
                 }

             }
             //Phase 2: Fill
             if (aFirstCrossIndex != -1)
             {
                 bool cursor = aEdges[aFirstCrossIndex].b;
                 for (int i = 0; i < aEdges.Count; i++)
                 {
                     var index = (i + aFirstCrossIndex)%aEdges.Count;
                     var edge = aEdges[index];
                     edge.b = cursor;
                     if (edge.p2.isCross)
                         cursor = !cursor;
                 }
             }
             if (bFirstCrossIndex != -1)
             {
                 bool cursor = bEdges[bFirstCrossIndex].a;
                 for (int i = 0; i < bEdges.Count; i++)
                 {
                     var index = (i + bFirstCrossIndex) % bEdges.Count;
                     var edge = bEdges[index];
                     edge.a = cursor;
                     if (edge.p2.isCross)
                         cursor = !cursor;
                 }
             }
             if (aFirstCrossIndex == -1 && bFirstCrossIndex == -1)
             {
                 //contains triangle area
                 var aV2 = aPoints.Select(x => (Vector2) x).ToArray();
                 var bV2 = bPoints.Select(x => (Vector2) x).ToArray();
                 if (isConvexPolygon(aV2) && isConvexPolygon(bV2))
                 {
                     if (contain.convex(aV2, bV2[0], true))
                     {
                         bEdges.ForEach(x => x.a = true);
                         var advancedEdge = new graphLine { a = true, aMain = true, b = false, p1 = MaxYItem(aPoints2D), p2 = MaxYItem(bPoints2D)};
                         aEdges.Add(advancedEdge);
                     } else if (contain.convex(bV2, aV2[0], true))
                     {
                         aEdges.ForEach(x => x.b = true);
                         var advancedEdge = new graphLine { b = true, aMain = false, a = false, p1 = MaxYItem(aPoints2D), p2 = MaxYItem(bPoints2D)};
                         bEdges.Add(advancedEdge);
                     }
                 }
                 else //if not convex
                 {
                     if (contain.nonzeroRule(aV2, bV2[0]))
                     {
                         bEdges.ForEach(x => x.a = true);
                         var advancedEdge = new graphLine { a = true, aMain = true, b = false, p1 = MaxYItem(aPoints2D), p2 = MaxYItem(bPoints2D) };
                         aEdges.Add(advancedEdge);
                     }
                     else if (contain.nonzeroRule(bV2, aV2[0]))
                     {
                         aEdges.ForEach(x => x.b = true);
                         var advancedEdge = new graphLine { b = true, aMain = false, a = false, p1 = MaxYItem(aPoints2D), p2 = MaxYItem(bPoints2D) };
                         bEdges.Add(advancedEdge);
                     }
                 }
             }
             return aEdges.Concat(bEdges).ToArray();
        }
Beispiel #3
0
        /// Проверяет факт пересечения, и возвращает помеченные ребра, если пересечение есть
        private static bool _detectIntersectionsIfNeed(graphLine a, graphLine b, out graphLine[] aOut, out graphLine[] bOut)
        {
            var a1 = a.p1.point;
             var a2 = a.p2.point;
             var b1 = b.p1.point;
             var b2 = b.p2.point;

             Vector2 cross;
             if (m.intersect.trySegments(a1, a2, b1, b2, false, out cross))
             {
                 var B1_isRight_of_A1A2 = isRight(a1, a2, b1);
                 var A1_isRight_of_B1B2 = isRight(b1, b2, a1);

                 float z;
                 if (a1.z != 0 && a2.z != 0)
                 {
                     var fullDistance = ((Vector2) a2 - (Vector2) a1).magnitude;
                     var partDistance = (cross - (Vector2) a1).magnitude;
                     var t = partDistance/fullDistance;
                     z = Mathf.Lerp(a1.z, a2.z, t);
                 }
                 else z = 0f;

                 var crossEx = new graphPoint(new Vector3(cross.x, cross.y, z), true);
                 aOut = a.Split(crossEx);
                 bOut = b.Split(crossEx);

                 aOut[0].b = A1_isRight_of_B1B2;
                 aOut[1].b = !A1_isRight_of_B1B2;

                 bOut[0].a = B1_isRight_of_A1A2;
                 bOut[1].a = !B1_isRight_of_A1A2;
                 return true;
             }
             aOut = null;
             bOut = null;
             return false;
        }
Beispiel #4
0
        public static List<polygon> calculatePolygons(graphLine[] edges)
        {
            var directedLines = new directedLine[edges.Length*2];
             //Создаем вектора
             for (int i = 0; i < edges.Length; i++)
             {
                 var edge = edges[i];
                 edge.ab = new directedLine { a = edge.p1, b = edge.p2, line = edge };
                 edge.ba = new directedLine { a = edge.p2, b = edge.p1, line = edge };
                 directedLines[i] = edge.ab;
                 directedLines[edges.Length + i] = edge.ba;
             }
             //Связываем правые стороны векторов
             for (int i = 0; i < edges.Length; i++)
             {
                 var edge = edges[i];
                 directedLines[i] = edge.ab;
                 directedLines[edges.Length + i] = edge.ba;

                 var nextAEdge = edge.GetRightEdge(edge.p1);
                 var nextBEdge = edge.GetRightEdge(edge.p2);
                 edge.ba.nextRightLine = nextAEdge.p1 == edge.p1 ? nextAEdge.ab : nextAEdge.ba;
                 edge.ab.nextRightLine = nextBEdge.p1 == edge.p2 ? nextBEdge.ab : nextBEdge.ba;
             }
             //Находим полигоны
             var polygons = new List<polygon>();
             for (int i = 0; i < directedLines.Length; i++)
             {
                 var dir = directedLines[i];
                 if (dir.used)
                     continue;

                 var path = new List<directedLine>();
                 int error = 0;
                 while (true)
                 {
                     dir.used = true;
                     path.Add(dir);

                     if (dir.nextRightLine.used)//exit
                     {
                         var firstIndex = path.IndexOf(dir.nextRightLine);
                         if (firstIndex == -1)
                             break;

                         var polygon = new polygon();
                         for (int j = firstIndex; j < path.Count; j++)
                         {
                             var e = path[j].line;
                             polygon.a &= e.a;
                             polygon.b &= e.b;

                             polygon.points.Add(path[j].b.point);
                         }
                         if (area.simplePolygon(polygon.points.Select(x => (Vector2)x).ToArray()) < 0f &&
                             (polygon.a || polygon.b))
                             polygons.Add(polygon);
                         break;
                     }
                     dir = dir.nextRightLine;

                     if (error >= directedLines.Length)
                     {
                         Debug.LogWarning("Error");
                         break;
                     }
                     error++;
                 }

             }
             return polygons;
        }