/// <summary> /// Creates IObstacle objects of this figure. /// </summary> /// <returns></returns> public virtual void Tokenize(ObstacleCollection obstacles) { if (Lines.Count == 0) { return; } GetForlorn(obstacles); if (Lines.Count == 0) { return; } if (SwitchPoints.Count > 0) { var polygons = SplitPolygon(Lines, obstacles); MergePolygons(polygons, obstacles); } else { var polygon = CreatePolygon(Lines); if (polygon.CheckIfFilled(Map, Layer, obstacles)) { AddPolygonObstacle(polygon, VerticesEx.IsRectangle(polygon), obstacles, Layer); } else { AddLineObstacles(polygon, obstacles, Layer); } } }
private void GetObstaclesPerLayer(int currentLayer, ObstacleCollection obstacles) { var rawObstacles = GetBlockObstacles(currentLayer); var nodes = new LineNodeDictionary(); nodes.CreateLineNodes(rawObstacles); while (nodes.Count > 0) { var currentFigure = new RawFigure(_map, currentLayer, nodes); nodes.Purge(currentFigure.Lines); currentFigure.Optimize(); currentFigure.Tokenize(obstacles); } nodes.Clear(); nodes.CreateLineNodes(rawObstacles, true); while (nodes.Count > 0) { var currentFigure = new SlopeFigure(_map, currentLayer, nodes); nodes.Purge(currentFigure.Lines); currentFigure.Optimize(); currentFigure.Tokenize(obstacles); } }
protected virtual void MergePolygons(IEnumerable <Polygon> polygons, ObstacleCollection obstacles) { /* * var filledPolygons = new List<Vertices>(); * var mergedPolygons = new List<Vertices>(); * * foreach (var polygon in polygons) * { * if (polygon.CheckIfFilled(Map, Layer, obstacles)) * filledPolygons.Add(polygon); * else * AddLineObstacles(polygon, obstacles, Layer); * } * * while (filledPolygons.Count > 0) * { * var polygon = filledPolygons.First(); * var changed = true; * while (changed) * { * changed = false; * var index = 0; * while (index < filledPolygons.Count) * { * var polygon2 = filledPolygons[index]; * var error = PolyClipError.None; * var combinedPolygons = polygon == polygon2 ? new List<Vertices> { polygon } : YuPengClipper.Union(polygon2, polygon, out error); * if (combinedPolygons.Count == 0) * { * //sometimes a polygon is a subset of the other polygon. Try to check that... * Vertices biggerPolygon; * if (VerticesEx.IsPolygonSubsetOf(polygon, polygon2, out biggerPolygon)) * { * combinedPolygons = new List<Vertices> { biggerPolygon }; * error = PolyClipError.None; //we could recover it... * } * } * //if (combinedPolygons.Count > 2) * // //the polygons intersect at several points, we ignore them as this would lead to holes... * //if (error != PolyClipError.None) * // //some error occurred, so we igore this union process... * if (combinedPolygons.Count == 1) //they intersect * { * filledPolygons.Remove(polygon2); * changed = true; * polygon = SimplifyTools.CollinearSimplify(combinedPolygons[0]); * } * else //combinedPolygons.Count > 1 --> they don't intersect (or may do at several points, but we ignore it ) * index++; * } * } * mergedPolygons.Add(polygon); * } * * foreach (var mergedPolygon in mergedPolygons) * AddPolygonObstacle(mergedPolygon, VerticesEx.IsRectangle(mergedPolygon), obstacles, Layer); * */ }
public override void Tokenize(ObstacleCollection obstacles) { /* * var polygons = SplitPolygon(Lines, obstacles); * var blocks = Polygon.GetAssociatedBlocks(polygons, Map, Layer).ToList(); * var polygonEdges = new List<LineSegment>(); * foreach (var polygon in polygons) * { * for (int i = 0, j = polygon.Count - 1; i < polygon.Count; j = i++) * polygonEdges.Add(GetLine(polygon[i], polygon[j], false, Lines)); * } * var intersectionLines = polygonEdges.GroupBy(x => x).Where(group => group.Count() > 1).Select(group => group.Key).ToList(); //finds duplicated items * * var blockLines = new Dictionary<Block, List<LineSegment>>(); //create a dictionary of block which intersection line they belong to. Because if the intersection line does not match, * //all intersecting lines of that block must be set invalid. Otherwise they engine would not not create a separate polygon. * var mismatchBlocks = new List<Block>(); * * foreach (var intersectionLine in intersectionLines) * { * Block blockX; * Block blockY; * Orientation orientation; * GetNeighborBlocks(intersectionLine, blocks, out blockX, out blockY, out orientation); * if (BlocksMatch(blockX, blockY, orientation)) * { * Lines.Remove(intersectionLine); * } * else * { * if (blockX != null & !mismatchBlocks.Contains(blockX)) * mismatchBlocks.Add(blockX); * if (blockY != null & !mismatchBlocks.Contains(blockY)) * mismatchBlocks.Add(blockY); * } * AddBlockLines(blockLines, blockX, intersectionLine); * AddBlockLines(blockLines, blockY, intersectionLine); * } * foreach (var mismatchBlock in mismatchBlocks) * { * //Restore all lines of the mismatched blocks * List<LineSegment> blockLineSegments; * if (!blockLines.TryGetValue(mismatchBlock, out blockLineSegments)) * continue; * foreach (var blockSegment in blockLineSegments.Where(blockSegment => !Lines.Contains(blockSegment))) * Lines.Add(blockSegment); * } * * polygons.Clear(); * polygons = SplitPolygon(Lines, obstacles); * foreach (var polygon in polygons) * { * var simplePolygon = SimplifyTools.CollinearSimplify(polygon); * AddSlopeObstacle(simplePolygon, VerticesEx.IsRectangle(simplePolygon), obstacles, Layer); * } * */ }
public bool CheckIfFilled(Map.Map map, int layer, ObstacleCollection obstacles) { Simplify(); var convexPolygons = BayazitDecomposer.ConvexPartition(this); var blockPointsDictionary = new Dictionary <Block, List <Vector2> >(); var blocks = GetAssociatedBlocks(convexPolygons, map, layer, blockPointsDictionary); var layerObstacles = CreateLayerObstacles(layer, obstacles); //ToDo: Don't call this method every time, the result does not change... return(CheckLid(blocks, map, layer, layerObstacles, blockPointsDictionary)); }
public ObstacleCollection GetObstacles() { var obstacles = new ObstacleCollection(); for (var i = 7; i >= 0; i--) { GetObstaclesPerLayer(i, obstacles); } obstacles.RemoveUnnecessary(); return(obstacles); }
public static ObstacleCollection Load(Map.Map map) { var obstacles = new ObstacleCollection(); /* * using (var reader = new BinaryReader(File.Open(map.Filename + ".col", FileMode.Open))) * { * reader.ReadString(); //GTA2.NET * reader.ReadString(); //Map Filename * var checksumLength = reader.ReadInt32(); //Checksum Length; * reader.ReadBytes(checksumLength); //Checksum * var obstacleCount = reader.ReadInt32(); //Obstacle count * for (var i = 0; i < obstacleCount; i++) * { * var type = reader.ReadByte(); * var obstacle = CreateObstacle((ObstacleType) type); * obstacle.IsSlope = reader.ReadBoolean(); * obstacle.Z = reader.ReadInt32(); * * if (obstacle is RectangleObstacle) * { * var rectangleObstacle = (RectangleObstacle) obstacle; * rectangleObstacle.X = reader.ReadSingle(); * rectangleObstacle.Y = reader.ReadSingle(); * rectangleObstacle.Width = reader.ReadSingle(); * rectangleObstacle.Length = reader.ReadSingle(); * } * else if (obstacle is LineObstacle) * { * var lineObstacle = (LineObstacle) obstacle; * lineObstacle.Start = new Vector2(reader.ReadSingle(), reader.ReadSingle()); * lineObstacle.End = new Vector2(reader.ReadSingle(), reader.ReadSingle()); * } * else if (obstacle is PolygonObstacle) * { * var polygonObstacle = (PolygonObstacle) obstacle; * var verticesCount = reader.ReadInt32(); * for (var j = 0; j < verticesCount; j++) * polygonObstacle.Vertices.Add(new Vector2(reader.ReadSingle(), reader.ReadSingle())); * } * obstacles.Add(obstacle); * } * * } */ return(obstacles); }
//Forlorn stuff /// <summary> /// Removes Forlorn out of the figure and converts them to LineObstacles. /// </summary> /// <param name="obstacles"></param> protected virtual void GetForlorn(ObstacleCollection obstacles) { var forlornNodes = new Queue <Vector2>(); foreach (var forlornNodeStart in ForlornStartNodes) { forlornNodes.Enqueue(forlornNodeStart); } while (forlornNodes.Count > 0) { var currentItem = forlornNodes.Dequeue(); List <LineSegment> forlornLines; Vector2 lastItemEndPoint; //this is needed for Switch Points below var forlornRoot = GetforlornRoot(currentItem, out forlornLines, out lastItemEndPoint); foreach (var line in forlornLines) { obstacles.Add(new LineObstacle(line.Start, line.End, Layer)); Lines.Remove(line); } if (SwitchPoints.Count == 0) { continue; } SwitchPoint switchPoint; if (!SwitchPoints.TryGetValue(forlornRoot, out switchPoint)) { continue; } if (switchPoint.EndPoints.Count > 0) { switchPoint.EndPoints.Remove(lastItemEndPoint); } if (switchPoint.EndPoints.Count == 1) { forlornNodes.Enqueue(forlornRoot); SwitchPoints.Remove(forlornRoot); } } ForlornStartNodes.Clear(); UpdateSwitchPoints(); }
/// <summary> /// Creates IObstacle objects of this figure. /// </summary> /// <returns></returns> public virtual void Tokenize(ObstacleCollection obstacles) { /* * if (Lines.Count == 0) * return; * GetForlorn(obstacles); * if (Lines.Count == 0) * return; * * if (SwitchPoints.Count > 0) * { * var polygons = SplitPolygon(Lines, obstacles); * MergePolygons(polygons, obstacles); * } * else * { * var polygon = CreatePolygon(Lines); * if (polygon.CheckIfFilled(Map, Layer, obstacles)) * AddPolygonObstacle(polygon, VerticesEx.IsRectangle(polygon), obstacles, Layer); * else * AddLineObstacles(polygon, obstacles, Layer); * } */ }
private static Dictionary <int, List <IObstacle> > CreateLayerObstacles(int layer, ObstacleCollection obstacles) { var dict = new Dictionary <int, List <IObstacle> >(); for (var z = layer + 1; z < 8; z++) { var layerObstacles = obstacles.Where(obstacle => obstacle.Z == z && (obstacle is PolygonObstacle || obstacle is RectangleObstacle)).ToList(); dict.Add(z, layerObstacles); } return(dict); }
protected static void AddPolygonObstacle(Vertices polygonVertices, bool isRectangle, ObstacleCollection obstacles, int layer) { if (isRectangle) { var rectangle = new RectangleObstacle(polygonVertices, layer); obstacles.Add(rectangle); } else { var polygonObstacle = new PolygonObstacle(polygonVertices, layer); obstacles.Add(polygonObstacle); } }
/// <summary> /// Splites a multi part figure into single parts. /// See Polygon Split.png. /// </summary> /// <param name="sourceSegments"></param> /// <param name="obstacles"></param> protected virtual ICollection <Polygon> SplitPolygon(List <LineSegment> sourceSegments, ObstacleCollection obstacles) { var verticesCombinations = new HashSet <Polygon>(); foreach (var switchPoint in SwitchPoints) { foreach (var endPoint in switchPoint.Value.EndPoints) { var startPoint = switchPoint.Key; var polygon = new Polygon(); var remainingLines = new List <LineSegment>(sourceSegments); var currentItem = startPoint; var currentDirection = Direction.None; do { if (currentItem == startPoint && polygon.Count > 0) { if (!verticesCombinations.Contains(polygon)) { verticesCombinations.Add(polygon); } break; } if (polygon.Contains(currentItem)) { break; } polygon.Add(currentItem); LineSegment preferedLine; if (currentItem == startPoint) { preferedLine = GetLine(currentItem, endPoint, true); } else { preferedLine = ChooseNextLine(currentItem, remainingLines, currentDirection); } if (preferedLine == null) { break; } currentItem = preferedLine.End; currentDirection = preferedLine.Direction; polygon.Lines.Add(preferedLine); remainingLines.Remove(preferedLine); } while (true); } } RemoveUnnecessaryPolygons(verticesCombinations); var forlornLines = GetPolygonForlornLines(sourceSegments, verticesCombinations); obstacles.AddRange(forlornLines.Select(forlornLine => new LineObstacle(forlornLine.Start, forlornLine.End, Layer))); return(verticesCombinations); }
/// <summary> /// Splites a multi part figure into single parts. /// See Polygon Split.png. /// </summary> /// <param name="sourceSegments"></param> /// <param name="obstacles"></param> protected virtual ICollection <Polygon> SplitPolygon(List <LineSegment> sourceSegments, ObstacleCollection obstacles) { var verticesCombinations = new HashSet <Polygon>(); /* * foreach (var switchPoint in SwitchPoints) * { * foreach (var endPoint in switchPoint.Value.EndPoints) * { * var startPoint = switchPoint.Key; * var polygon = new Polygon(); * var remainingLines = new List<LineSegment>(sourceSegments); * var currentItem = startPoint; * var currentDirection = Direction.None; * do * { * if (currentItem == startPoint && polygon.Count > 0) * { * if (!verticesCombinations.Contains(polygon)) * verticesCombinations.Add(polygon); * break; * } * if (polygon.Contains(currentItem)) * break; * polygon.Add(currentItem); * LineSegment preferedLine; * if (currentItem == startPoint) * preferedLine = GetLine(currentItem, endPoint, true); * else * preferedLine = ChooseNextLine(currentItem, remainingLines, currentDirection); * if (preferedLine == null) * break; * currentItem = preferedLine.End; * currentDirection = preferedLine.Direction; * polygon.Lines.Add(preferedLine); * remainingLines.Remove(preferedLine); * } while (true); * } * } * RemoveUnnecessaryPolygons(verticesCombinations); * * var forlornLines = GetPolygonForlornLines(sourceSegments, verticesCombinations); * obstacles.AddRange(forlornLines.Select(forlornLine => new LineObstacle(forlornLine.Start, forlornLine.End, Layer))); */ return(verticesCombinations); }