Beispiel #1
0
        public static bool IsShapeConvex(Polygon shape)
        {
            PolygonShapeData shapeData = shape.Data as PolygonShapeData;

            for (int i = 0; i < shapeData.PolygonPoints.Count; i++)
            {
                Vector2 first  = shapeData.PolygonPoints[i];
                int     sI     = i == shapeData.PolygonPoints.Count - 1 ? 0 : i + 1;
                Vector2 second = shapeData.PolygonPoints[sI];
                for (int j = 0; j < shapeData.PolygonPoints.Count; j++)
                {
                    Vector2 pointToCheck = shapeData.PolygonPoints[j];
                    if (pointToCheck != first && pointToCheck != second)
                    {
                        bool isConvex = ((second.X - first.X) * (pointToCheck.Y - first.Y) - (second.Y - first.Y) * (pointToCheck.X - first.X)) > 0;

                        if (!isConvex)
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
Beispiel #2
0
 public PolygonShapeData(PolygonShapeData self)
 {
     Depth         = self.Depth;
     Scalar        = self.Scalar;
     PolygonPoints = new List <Vector2>();
     for (int i = 0; i < self.PolygonPoints.Count; i++)
     {
         PolygonPoints.Add(self.PolygonPoints[i]);
     }
 }
Beispiel #3
0
        public void CalculatePreGenerateData()
        {
            PolygonShapeData shapeData = Data as PolygonShapeData;

            for (int i = 0; i < shapeData.PolygonPoints.Count; i++)
            {
                int pointX = (int)MathF.Round(shapeData.PolygonPoints[i].X * shapeData.Scalar, 0, MidpointRounding.ToEven);
                int pointY = (int)MathF.Round(shapeData.PolygonPoints[i].Y * shapeData.Scalar, 0, MidpointRounding.ToEven);

                shapeData.PolygonPoints[i] = new Vector2(pointX, pointY);
            }
        }
Beispiel #4
0
        public Vector2 GetCenter()
        {
            PolygonShapeData shapeData = Data as PolygonShapeData;
            Vector2          center    = new Vector2(0, 0);

            for (int i = 0; i < shapeData.PolygonPoints.Count; i++)
            {
                center += shapeData.PolygonPoints[i] * shapeData.Scalar;
            }

            center /= shapeData.PolygonPoints.Count;

            return(center);
        }
Beispiel #5
0
 public Polygon(Polygon self) : base(self)
 {
     ID       = self.ID;
     Position = self.Position;
     if (self.Sides != null)
     {
         Sides = new SolidSide[self.Sides.Length];
     }
     if (Sides != null)
     {
         for (int i = 0; i < self.Sides.Length; i++)
         {
             Sides[i] = self.Sides[i];
         }
     }
     Data = new PolygonShapeData(self.Data as PolygonShapeData);
 }
Beispiel #6
0
        private List <Shape> ConvertToConvex(Polygon shape)
        {
            PolygonShapeData shapeData = shape.Data as PolygonShapeData;

            List <List <Vector2> > result       = PolygonTriangulator.Triangulate(shapeData.PolygonPoints);
            List <Shape>           newShapeList = new List <Shape>();

            for (int i = 0; i < result.Count; i++)
            {
                Polygon        newShape = new Polygon(shape);
                List <Vector2> points   = result[i];
                //points.Reverse();
                newShape.Data = new PolygonShapeData()
                {
                    Depth         = shapeData.Depth,
                    Scalar        = shapeData.Scalar,
                    PolygonPoints = points
                };
                newShapeList.Add(newShape);
            }

            return(newShapeList);
        }
Beispiel #7
0
        public static void CombineShapes(List <Polygon> shapes, out List <Polygon> resultingShapes, int depth = 0)
        {
            List <Polygon> applicants = new List <Polygon>();

            Polygon        currentPolygonToEval = null;
            List <Polygon> options = new List <Polygon>(shapes);
            int            save    = 0;

            while (true)
            {
                if (currentPolygonToEval == null)
                {
                    if (options.Count <= 0)
                    {
                        break;
                    }
                    currentPolygonToEval = options[0];
                    options.RemoveAt(0);
                }

                Polygon prev           = null;
                Polygon found          = null;
                bool    anyCombination = false;
                for (int i = 0; i < options.Count; i++)
                {
                    Polygon v = new Polygon(currentPolygonToEval);
                    v = v.Combine(options[i]);

                    if (v != null)
                    {
                        v = RemoveRedundantPoints(v);
                        if (IsShapeConvex(v))
                        {
                            found = options[i];
                            prev  = new Polygon(currentPolygonToEval);
                            currentPolygonToEval = v;
                            options.RemoveAt(i);
                            anyCombination = true;
                            break;
                        }
                    }
                }

                VMFDebug.CreateDebugImage("CombiningStep" + (save++), onDraw: (g) =>
                {
                    Pen greyPen  = new Pen(Color.Gray, 3);
                    Pen blackPen = new Pen(Color.Black, 3);
                    Pen redPen   = new Pen(Color.Red, 3);
                    Pen bluePen  = new Pen(Color.Blue, 3);
                    Pen greenPen = new Pen(Color.Green, 3);

                    for (int i = 0; i < options.Count; i++)
                    {
                        VMFDebug.AddShapeToGraphics(g, options[i], greyPen);
                    }

                    for (int i = 0; i < applicants.Count; i++)
                    {
                        VMFDebug.AddShapeToGraphics(g, applicants[i], blackPen);
                    }

                    if (found != null)
                    {
                        VMFDebug.AddShapeToGraphics(g, found, bluePen);
                    }

                    if (prev != null)
                    {
                        VMFDebug.AddShapeToGraphics(g, prev, greenPen);
                    }
                    else
                    {
                        VMFDebug.AddShapeToGraphics(g, currentPolygonToEval, redPen);
                    }
                });

                if (!anyCombination)
                {
                    applicants.Add(new Polygon(currentPolygonToEval));
                    currentPolygonToEval = null;
                }
            }

            List <Polygon> result = new List <Polygon>();

            for (int i = 0; i < applicants.Count; i++)
            {
                bool canAdd = true;
                for (int j = 0; j < result.Count; j++)
                {
                    PolygonShapeData rSD = result[j].Data as PolygonShapeData;
                    PolygonShapeData aSD = applicants[i].Data as PolygonShapeData;
                    if (rSD.PolygonPoints.SequenceEqual(aSD.PolygonPoints))
                    {
                        canAdd = false;
                        break;
                    }
                }
                if (canAdd)
                {
                    result.Add(applicants[i]);
                }
            }

            resultingShapes = result;
        }
Beispiel #8
0
        private void GenerateData(out List <Shape> shapesResult, out List <string> entities)
        {
            List <GenerationMethod> generationMethods = new List <GenerationMethod>();

            entities = new List <string>();
            EasyInputLayer.GetInput(out generationMethods, out entities);

            //Start shape construction
            List <Shape> shapes = new List <Shape>();

            for (int i = 0; i < generationMethods.Count; i++)
            {
                shapes.AddRange(generationMethods[i].GetBrushes());
            }

            List <Shape> finalShapeList = new List <Shape>();

            for (int i = shapes.Count - 1; i >= 0; i--)
            {
                if (shapes[i] is Polygon)
                {
                    (shapes[i] as Polygon).CalculatePreGenerateData();

                    if (!IsShapeConvex(shapes[i] as Polygon))
                    {
                        VMFDebug.CreateDebugImage("PreTriangulation" + (i), onDraw: (g) =>
                        {
                            Pen greyPen = new Pen(Color.Gray, 3);
                            Pen redPen  = new Pen(Color.Red, 3);
                            for (int j = 0; j < shapes.Count; j++)
                            {
                                if (shapes[j] is Polygon)
                                {
                                    VMFDebug.AddShapeToGraphics(g, shapes[j] as Polygon, greyPen);
                                }
                            }
                            VMFDebug.AddShapeToGraphics(g, shapes[i] as Polygon, redPen);
                        });


                        Console.WriteLine("Found a concave shape. Attempting triangulation");
                        List <Polygon> replacements = new List <Polygon>();
                        List <Shape>   temp         = ConvertToConvex(shapes[i] as Polygon);

                        for (int j = 0; j < temp.Count; j++)
                        {
                            replacements.Add(temp[j] as Polygon);
                        }

                        Console.WriteLine("Single shape converted into " + replacements.Count + " new shapes");

                        List <Polygon> combinedShapes = new List <Polygon>();

                        for (int j = replacements.Count - 1; j >= 0; j--)
                        {
                            if (!IsShapeConvex(replacements[j] as Polygon))
                            {
                                replacements[j] = RemoveRedundantPoints(replacements[j] as Polygon);
                                Console.WriteLine("An invalid shape was found in the replacement batch. Attempting to fix...");

                                if (((PolygonShapeData)replacements[j].Data).PolygonPoints.Count < 3 || !IsShapeConvex(replacements[j] as Polygon))
                                {
                                    Console.WriteLine("Could not fix invalid shape. Deleting.");
                                    replacements.RemoveAt(j);
                                }
                                else
                                {
                                    Console.WriteLine("Invalid shape fixed!");
                                }
                            }
                        }

                        combinedShapes = replacements;
                        CombineShapes(replacements, out combinedShapes);

                        PolygonShapeData shapeData = shapes[i].Data as PolygonShapeData;
                        for (int j = 0; j < combinedShapes.Count; j++)
                        {
                            finalShapeList.Add(combinedShapes[j]);
                        }
                    }
                    else
                    {
                        finalShapeList.Add(shapes[i] as Polygon);
                    }
                }
                else
                {
                    finalShapeList.Add(shapes[i]);
                }
            }

            int currId = 0;

            for (int i = 0; i < finalShapeList.Count; i++)
            {
                finalShapeList[i].ID = i;
                finalShapeList[i].GenerateSides(currId);
                currId += finalShapeList[i].Sides.Length;
            }
            //End shape construction

            shapesResult = finalShapeList;
        }
Beispiel #9
0
        public static List <Polygon> CreateWalls(Polygon polygon, WallData wallData)
        {
            List <List <Vector2> > allPoints = new List <List <Vector2> >();
            List <Vector2>         points    = new List <Vector2>();
            List <Vector2>         lastFace  = new List <Vector2>();
            List <List <Vector2> > normals   = new List <List <Vector2> >();

            PolygonShapeData polyData = polygon.Data as PolygonShapeData;

            List <Vector2> sharedValues = polyData.PolygonPoints.GroupBy(x => x).Where(g => g.Count() > 1).Select(x => x.Key).ToList();

            for (int i = 0; i < polyData.PolygonPoints.Count; i++)
            {
                if (sharedValues.Contains(polyData.PolygonPoints[i]))
                {
                    wallData.facesIndicesToSkip.Add(i);
                    i++;
                }
            }

            for (int i = 0; i < polyData.PolygonPoints.Count; i++)
            {
                if (wallData.facesIndicesToSkip.Contains(i))
                {
                    continue;
                }

                //Okay basically all the shit I'm doing here is getting the vertex normal of the current point
                //and basing how the wall should be made based off that, so all the walls end up as trapazoids.
                //The only exception is if a wall piece is missing, I then get the intersection based on which
                //side of the wall it is, and try to flatten it. It's not perfect but it works?
                int index1 = (i - 1) % polyData.PolygonPoints.Count;
                if (index1 == -1)
                {
                    index1 = polyData.PolygonPoints.Count - 1;
                }
                int     index2 = i % polyData.PolygonPoints.Count;
                int     index3 = (i + 1) % polyData.PolygonPoints.Count;
                int     index4 = (i + 2) % polyData.PolygonPoints.Count;
                Vector2 a      = polyData.PolygonPoints[index1] * polyData.Scalar;
                Vector2 b      = polyData.PolygonPoints[index2] * polyData.Scalar;
                Vector2 c      = polyData.PolygonPoints[index3] * polyData.Scalar;
                Vector2 d      = polyData.PolygonPoints[index4] * polyData.Scalar;

                Vector2 abNormal        = Vector2.Normalize(Shape.GetNormal2D(a, b));
                Vector2 bcNormal        = Vector2.Normalize(Shape.GetNormal2D(b, c));
                Vector2 vertexNormalabc = Vector2.Normalize((abNormal + bcNormal)) * wallData.Thickness;
                Vector2 cdNormal        = Vector2.Normalize(Shape.GetNormal2D(c, d));
                Vector2 vertexNormalbcd = Vector2.Normalize((bcNormal + cdNormal)) * wallData.Thickness;

                Vector2 point  = polyData.PolygonPoints[index2] * polyData.Scalar + vertexNormalabc;
                Vector2 point2 = polyData.PolygonPoints[index3] * polyData.Scalar + vertexNormalbcd;
                points.Add(point);
                points.Add(point2);
                points.Add(c);
                points.Add(b);

                if (wallData.facesIndicesToSkip.Contains(i + 1))
                {
                    LineEquation first  = new LineEquation(points[2], points[2] - bcNormal);
                    LineEquation second = new LineEquation(points[0], points[1]);
                    Vector2      intersectPoint;
                    if (first.IntersectsWithLine(second, out intersectPoint))
                    {
                        points[1] = intersectPoint;
                    }
                }
                if (wallData.facesIndicesToSkip.Contains(i - 1))
                {
                    LineEquation first  = new LineEquation(points[3], points[3] - bcNormal);
                    LineEquation second = new LineEquation(points[0], points[1]);
                    Vector2      intersectPoint;
                    if (first.IntersectsWithLine(second, out intersectPoint))
                    {
                        points[0] = intersectPoint;
                    }
                }

                allPoints.Add(points);
                points = new List <Vector2>();
            }

            //Idk there were edge cases I had NAN values and they didnt seem to affect anything sooooooo
            for (int i = allPoints.Count - 1; i >= 0; i--)
            {
                bool hasNan = false;
                for (int j = 0; j < allPoints[i].Count; j++)
                {
                    if (allPoints[i][j] != allPoints[i][j])
                    {
                        hasNan = true;
                        break;
                    }
                }

                if (hasNan)
                {
                    allPoints.RemoveAt(i);
                }
            }

            VMFDebug.CreateDebugImage("WallOutput", onDraw: (g) =>
            {
                float scale = 0.1f;
                for (int i = 0; i < allPoints.Count; i++)
                {
                    for (int j = 0; j < allPoints[i].Count; j++)
                    {
                        int iN   = (j + 1) % allPoints[i].Count;
                        Point p1 = new Point((int)(allPoints[i][j].X * scale + 100), (int)(allPoints[i][j].Y * scale + 100));
                        Point p2 = new Point((int)(allPoints[i][iN].X * scale + 100), (int)(allPoints[i][iN].Y * scale + 100));

                        g.DrawLine(new Pen(Color.Black, 3), p1, p2);
                    }
                }
            });

            List <Polygon> finalPolygons = new List <Polygon>();

            for (int i = 0; i < allPoints.Count; i++)
            {
                finalPolygons.Add(
                    new Polygon()
                {
                    Position = polygon.Position + new Vector3(0, 0, wallData.Height * 0.5f),
                    Data     = new PolygonShapeData()
                    {
                        Depth         = wallData.Height + ((PolygonShapeData)polygon.Data).Depth,
                        Scalar        = 1,
                        PolygonPoints = allPoints[i]
                    }
                });
            }

            return(finalPolygons);
        }
Beispiel #10
0
        public Polygon Combine(Polygon other)
        {
            PolygonShapeData myShapeData = Data as PolygonShapeData;
            PolygonShapeData shapeData   = other.Data as PolygonShapeData;

            List <Vector2> sharedPoints     = new List <Vector2>();
            int            lowestIndexMe    = -1;
            int            lowestIndexOther = -1;
            Vector2        lowestMe         = new Vector2(99999999, 99999999);
            Vector2        lowestOther      = new Vector2(99999999, 99999999);
            Vector2        lowest           = new Vector2(99999999, 99999999);

            for (int i = 0; i < myShapeData.PolygonPoints.Count; i++)
            {
                if (shapeData.PolygonPoints.Contains(myShapeData.PolygonPoints[i]))
                {
                    sharedPoints.Add(myShapeData.PolygonPoints[i]);
                }

                if (myShapeData.PolygonPoints[i].X < lowest.X || (myShapeData.PolygonPoints[i].X == lowest.X && myShapeData.PolygonPoints[i].Y < lowest.Y))
                {
                    lowest = myShapeData.PolygonPoints[i];
                }

                if (myShapeData.PolygonPoints[i].X < lowestMe.X || (myShapeData.PolygonPoints[i].X == lowestMe.X && myShapeData.PolygonPoints[i].Y < lowestMe.Y))
                {
                    lowestMe      = myShapeData.PolygonPoints[i];
                    lowestIndexMe = i;
                }
            }

            if (sharedPoints.Count <= 1)
            {
                return(null);
            }

            for (int i = 0; i < shapeData.PolygonPoints.Count; i++)
            {
                if (shapeData.PolygonPoints[i].X < lowest.X || (shapeData.PolygonPoints[i].X == lowest.X && shapeData.PolygonPoints[i].Y < lowest.Y))
                {
                    lowest = shapeData.PolygonPoints[i];
                }

                if (shapeData.PolygonPoints[i].X < lowestOther.X || (shapeData.PolygonPoints[i].X == lowestOther.X && shapeData.PolygonPoints[i].Y < lowestOther.Y))
                {
                    lowestOther      = shapeData.PolygonPoints[i];
                    lowestIndexOther = i;
                }
            }

            bool startOnMe = false;
            int  currIndex = -1;

            if (lowestMe != lowestOther)
            {
                if (lowestMe.X == lowestOther.X)
                {
                    startOnMe = lowestMe.Y < lowestOther.Y;
                }
                else
                {
                    startOnMe = lowestMe.X < lowestOther.X;
                }
            }
            else
            {
                int lowestMeNext = lowestIndexMe + 1;
                if (lowestMeNext >= myShapeData.PolygonPoints.Count)
                {
                    lowestMeNext = 0;
                }
                int lowestOtherNext = lowestIndexOther + 1;
                if (lowestOtherNext >= shapeData.PolygonPoints.Count)
                {
                    lowestOtherNext = 0;
                }
                Vector2 mePointOption    = myShapeData.PolygonPoints[lowestMeNext];
                Vector2 otherPointOption = shapeData.PolygonPoints[lowestOtherNext];

                float   constantAngle   = MathF.Atan2(0.5f, 1) * 180 / MathF.PI;
                Vector2 meDifference    = Vector2.Normalize(mePointOption - lowest);
                float   meAngle         = MathF.Atan2(meDifference.X, meDifference.Y) * 180 / MathF.PI;
                Vector2 otherDifference = Vector2.Normalize(otherPointOption - lowest);
                float   otherAngle      = MathF.Atan2(otherDifference.X, otherDifference.Y) * 180 / MathF.PI;

                startOnMe = meAngle > otherAngle;
            }

            currIndex = startOnMe ? lowestIndexMe : lowestIndexOther;

            List <Vector2> startingList  = startOnMe ? myShapeData.PolygonPoints : shapeData.PolygonPoints;
            Vector2        firstPosition = startingList[currIndex];
            List <Vector2> newShapeList  = new List <Vector2>();

            int safety = 0;

            while (true)
            {
                Vector2 pos = startingList[currIndex];

                if (pos == firstPosition && newShapeList.Count > 0)
                {
                    break;
                }

                newShapeList.Add(pos);

                if (sharedPoints.Contains(pos) && newShapeList.Count > 1)
                {
                    startingList = startOnMe ? shapeData.PolygonPoints : myShapeData.PolygonPoints;

                    for (int i = 0; i < startingList.Count; i++)
                    {
                        if (startingList[i] == pos)
                        {
                            currIndex = i;
                            break;
                        }
                    }

                    startOnMe = !startOnMe;
                }

                currIndex++;
                if (currIndex >= startingList.Count)
                {
                    currIndex = 0;
                }

                safety++;
                if (safety > 1000)
                {
                    break;
                }
            }

            PolygonShapeData finalData = new PolygonShapeData(myShapeData);

            finalData.PolygonPoints = newShapeList;

            Polygon topVertex = new Polygon(other)
            {
                ID       = other.ID,
                Position = other.Position,
                Sides    = other.Sides,
                Data     = finalData
            };

            return(topVertex);
        }
Beispiel #11
0
        public override void GenerateSides(int startingID)
        {
            PolygonShapeData shapeData = Data as PolygonShapeData;

            //For now we only do cubes
            Sides = new SolidSide[shapeData.PolygonPoints.Count + 2];

            for (int i = 0; i < Sides.Length; i++)
            {
                Sides[i].ID = startingID + i;
            }

            //Top
            Sides[0].Plane = new Vector3[]
            {
                Position + new Vector3(-shapeData.Scalar, -shapeData.Scalar, (shapeData.Depth * 0.5f)),
                Position + new Vector3(-shapeData.Scalar, shapeData.Scalar, (shapeData.Depth * 0.5f)),
                Position + new Vector3(shapeData.Scalar, shapeData.Scalar, (shapeData.Depth * 0.5f))
            };
            Sides[0].UV = new Vector4[]
            {
                new Vector4(1, 0, 0, 0),
                new Vector4(0, 1, 0, 0)
            };

            //Bottom
            Sides[1].Plane = new Vector3[]
            {
                Position + new Vector3(shapeData.Scalar, -shapeData.Scalar, -(shapeData.Depth * 0.5f)),
                Position + new Vector3(shapeData.Scalar, shapeData.Scalar, -(shapeData.Depth * 0.5f)),
                Position + new Vector3(-shapeData.Scalar, shapeData.Scalar, -(shapeData.Depth * 0.5f))
            };
            Sides[1].UV = new Vector4[]
            {
                new Vector4(1, 0, 0, 0),
                new Vector4(0, 1, 0, 0)
            };

            for (int i = 0; i < shapeData.PolygonPoints.Count; i++)
            {
                int     sidesIndex = 2 + i;
                Vector2 first      = shapeData.PolygonPoints[i];
                int     sI         = i == shapeData.PolygonPoints.Count - 1 ? 0 : i + 1;
                Vector2 second     = shapeData.PolygonPoints[sI];

                float angle = MathF.Atan2(second.Y - first.Y, second.X - first.X) * (180 / MathF.PI);
                if (angle < 0)
                {
                    angle += 360;
                }

                Sides[sidesIndex].Plane = new Vector3[]
                {
                    Position + new Vector3(first.X, first.Y, -(shapeData.Depth * 0.5f)),
                    Position + new Vector3(first.X, first.Y, (shapeData.Depth * 0.5f)),
                    Position + new Vector3(second.X, second.Y, (shapeData.Depth * 0.5f))
                };

                bool useFirstMethod = (angle > 0 && angle <= 90) || (angle > 180 && angle <= 270);
                if (useFirstMethod)
                {
                    Sides[sidesIndex].UV = new Vector4[]
                    {
                        new Vector4(0, 1, 0, 0),
                        new Vector4(0, 0, -1, 0)
                    };
                }
                else
                {
                    Sides[sidesIndex].UV = new Vector4[]
                    {
                        new Vector4(1, 0, 0, 0),
                        new Vector4(0, 0, -1, 0)
                    };
                }
            }

            base.GenerateSides(startingID);
        }