/// <summary> /// 生成外轮廓多边形 /// </summary> /// <param name="grid"></param> /// <param name="me"></param> /// <param name="startSearchPoint"></param> /// <param name="limitDistance"></param> /// <param name="isBlockOutPoly">是否为挡格的轮廓多边形,是的时候需要倒序处理</param> /// <returns></returns> private static ContourPoly GeneralOutPoly(RLEGridMap grid, MapElement me, Float2 startSearchPoint, float limitDistance, bool isBlockOutPoly) { ContourPoly poly = new ContourPoly(); List <Double2> points = me.GetContourPoints(grid, startSearchPoint); if (isBlockOutPoly == true) { points.Reverse(); } List <int> listIndex = ConvexPolygon2D.GenerateConvexPolygonIndex(points.ToArray()); List <Double2> polys = new List <Double2>(); for (int i = 0; i < listIndex.Count; i++) { if (i < listIndex.Count - 1) { OptimizationContourConvexLine(listIndex[i], listIndex[i + 1], false, limitDistance, points, ref polys); } else { OptimizationContourConvexLine(listIndex[i], listIndex[0], true, limitDistance, points, ref polys); } } poly.InitData(polys); return(poly); }
/// <summary> /// 生成轮廓数据 /// </summary> /// <param name="grid"></param> /// <param name="limitDistance"></param> /// <param name="ret"></param> public void GeneralContour(RLEGridMap grid, ref ContourData ret) { if (ret == null) { ret = new ContourData(); } ret.Clear(); ret.tileSize = (int)grid.TileSize; ret.sdfValue = (int)grid.SdfValue; ret.width = grid.tileXnum * ret.tileSize; ret.height = grid.tileYnum * ret.tileSize; float limitDistance = ret.tileSize; for (int i = 0; i < this.myArea.Count; i++) { MapArea submap = this.myArea[i]; ContourUnit unit = ContourOptimization.GeneralContourUnit(grid, submap, limitDistance); ret.AddAreaMap(unit); } for (int i = 0; i < this.mydoor.Count; i++) { StageGateArea stage = this.mydoor[i]; ContourUnit unit = ContourOptimization.GeneralContourUnit(grid, stage, limitDistance); unit.SetDoorData(stage.MindoorCenter, stage.MaxdoorCenter, stage.isXdir, grid.TileSize, i); ret.AddStage(unit); } // 分析连接关系 ret.ParseDoorLink(); }
/// <summary> /// 在轮廓中查找keyPoint /// </summary> /// <returns></returns> public bool FindKeyPoint(RLEGridMap grid, ref Float2 keyPoint) { if (grid == null) { return(false); } Polygon2D poly = new Polygon2D(pts.ToArray()); Double2 lb = poly.leftBottom; Double2 ru = poly.rightUp; Short2 slb = grid.GetIndex(lb) + Short2.one; Short2 sru = grid.GetIndex(ru) - Short2.one; for (int x = slb.x; x < sru.x; x++) { double xpos = x * (double)grid.TileSize; Double2 yminPos1 = Double2.zero; Double2 ymaxPos2 = Double2.zero; if (poly.GetPointsInAreabyXaixs(xpos, 1.0f, ref yminPos1, ref ymaxPos2) == true) { int ymin = (int)(yminPos1.y / grid.TileSize); int ymax = (int)(ymaxPos2.y / grid.TileSize); if (grid.CheckXDirHaveBlock(x, ymin, ymax) == true) { keyPoint = new Float2(x * grid.TileSize, ymax * grid.TileSize); return(true); } } } return(false); }
/// <summary> /// 生成外轮廓多边形 /// </summary> /// <param name="grid"></param> /// <param name="limitDistance"></param> /// <returns></returns> public static ContourUnit GeneralContourUnit(RLEGridMap grid, MapElement me, float limitDistance) { ContourPoly poly = GeneralOutPoly(grid, me, me.GetKeyPoint(), limitDistance, false); ContourUnit unit = new ContourUnit(poly);; if (me is MapArea) { Float2 keyPoint = Float2.zero; while (poly.FindKeyPoint(grid, ref keyPoint) == true) { ContourPoly poly1 = GeneralOutPoly(grid, me, keyPoint, limitDistance, true); unit.AddBlockPoly(poly1); } } return(unit); }
/// <summary> /// 获取轮廓 /// </summary> /// <param name="grid"></param> /// <returns></returns> public virtual List <Double2> GetContourPoints(RLEGridMap grid, Float2 startSearchPoint) { List <Double2> listPoint = new List <Double2>(); Short2 ContourStartPoint = Short2.zero; Short2 ContourStartBlockPoint = Short2.zero; if (GetStartingPoint(ref ContourStartPoint, ref ContourStartBlockPoint, startSearchPoint, grid) == true) { List <Short2> list = MarchingSquares(ContourStartPoint, grid); foreach (Short2 v in list) { Double2 pos = new Double2(v.x, v.y) * grid.TileSize; listPoint.Add(pos); } // 轮廓挡格区域点。 不能这样清理哦。 grid.EmptyContinuousBlock(ContourStartBlockPoint); //Core.BlockTool.BlockTexureExport.SaveBlockTexture(2, grid); } return(listPoint); }
/// <summary> /// 使用移动cubes 获取轮廓线。Contour 轮廓 /// </summary> /// <returns></returns> public List <Short2> MarchingSquares(Short2 startPoint, RLEGridMap grid) { List <Short2> listPoint = new List <Short2>(); int pX = startPoint.x; int pY = startPoint.y; int stepX = 0; int stepY = 0; int prevX = 0; int prevY = 0; bool closedLoop = false; while (!closedLoop) { // the core of the script is getting the 2x2 square value of each pixel int squareValue = grid.GetSquareValue(pX, pY); switch (squareValue) { /* going UP with these cases: +---+---+ +---+---+ +---+---+ | 1 | | | 1 | | | 1 | | +---+---+ +---+---+ +---+---+ | | | | 4 | | | 4 | 8 | +---+---+ +---+---+ +---+---+ */ case 1: case 5: case 13: stepX = 0; stepY = -1; break; /* going DOWN with these cases: +---+---+ +---+---+ +---+---+ | | | | | 2 | | 1 | 2 | +---+---+ +---+---+ +---+---+ | | 8 | | | 8 | | | 8 | +---+---+ +---+---+ +---+---+ */ case 8: case 10: case 11: stepX = 0; stepY = 1; break; /* going LEFT with these cases: * +---+---+ +---+---+ +---+---+ | | | | | | | | 2 | +---+---+ +---+---+ +---+---+ | 4 | | | 4 | 8 | | 4 | 8 | +---+---+ +---+---+ +---+---+ */ case 4: case 12: case 14: stepX = -1; stepY = 0; break; /* going RIGHT with these cases: * +---+---+ +---+---+ +---+---+ | | 2 | | 1 | 2 | | 1 | 2 | +---+---+ +---+---+ +---+---+ | | | | | | | 4 | | +---+---+ +---+---+ +---+---+ */ case 2: case 3: case 7: stepX = 1; stepY = 0; break; case 6: /* special saddle point case 1: +---+---+ | | 2 | +---+---+ | 4 | | +---+---+ | going LEFT if coming from UP | else going RIGHT | */ if (prevX == 0 && prevY == -1) { stepX = -1; stepY = 0; } else { stepX = 1; stepY = 0; } break; case 9: /* special saddle point case 2: * +---+---+ | 1 | | +---+---+ | | 8 | +---+---+ | | going UP if coming from RIGHT | else going DOWN | */ if (prevX == 1 && prevY == 0) { stepX = 0; stepY = -1; } else { stepX = 0; stepY = 1; } break; } // moving onto next point pX += stepX; pY += stepY; // saving contour point listPoint.Add(new Short2(pX, pY)); prevX = stepX; prevY = stepY; // if we returned to the first point visited, the loop has finished if (pX == startPoint.x && pY == startPoint.y) { closedLoop = true; } } return(listPoint); }
/// <summary> /// 获取轮廓起点及轮廓挡格起点 /// </summary> /// <param name="ContourStartPoint">轮廓起点</param> /// <param name="ContourStartBlockPoint">轮廓挡格起点</param> /// <param name="startSearchPoint">悬针搜索点</param> /// <param name="grid"></param> /// <returns></returns> public bool GetStartingPoint(ref Short2 ContourStartPoint, ref Short2 ContourStartBlockPoint, Float2 startSearchPoint, RLEGridMap grid) { Short2 center = grid.GetIndex(startSearchPoint); if (grid.CheckInMap(center) == false) { return(false); } for (int j = 0; j <= center.y; j++) { if (grid.CheckBlock(center - new Short2(0, j)) == true) { ContourStartPoint = center - new Short2(0, j - 1); ContourStartBlockPoint = center - new Short2(0, j); return(true); } } return(false); }