FieldConnectPoint ToFieldConnectPoint(RiverPoint riverPoint) { var point = new FieldConnectPoint(); point.Initialize(riverPoint.Position, PointType.kRiver); return(point); }
void DetectSquareArea(List <FieldConnectPoint> roadPoints) { for (int i0 = 0; i0 < roadPoints.Count; ++i0) { FieldConnectPoint point = roadPoints[i0]; List <FieldConnectPoint> connectedPoints = point.ConnectionList; for (int i1 = 0; i1 < connectedPoints.Count; ++i1) { FieldConnectPoint connectedPoint = connectedPoints[i1]; List <FieldConnectPoint> candidates = connectedPoint.ConnectionList; for (int i2 = i1 + 1; i2 < connectedPoints.Count; ++i2) { FieldConnectPoint connectedPoint2 = connectedPoints[i2]; List <FieldConnectPoint> candidates2 = connectedPoint2.ConnectionList; for (int i3 = 0; i3 < candidates.Count; ++i3) { FieldConnectPoint candidate = candidates[i3]; if (candidate.Index != point.Index) { if (candidates2.Contains(candidate) != false) { var areaPoints = new List <FieldConnectPoint> { point, connectedPoint, candidate, connectedPoint2, }; if (IsExistCombination(areaPoints) == false) { AddCombination(areaPoints); int disconnectionIndex = candidates.FindIndex(p => p.Index == connectedPoint2.Index); if (disconnectionIndex >= 0) { connectedPoint.Disconnection(disconnectionIndex); disconnectionIndex = candidates2.FindIndex(p => p.Index == connectedPoint.Index); if (disconnectionIndex >= 0) { connectedPoint2.Disconnection(disconnectionIndex); } } disconnectionIndex = connectedPoints.FindIndex(p => p.Index == candidate.Index); if (disconnectionIndex >= 0) { point.Disconnection(disconnectionIndex); disconnectionIndex = candidate.ConnectionList.FindIndex(p => p.Index == point.Index); if (disconnectionIndex >= 0) { candidate.Disconnection(disconnectionIndex); } } AddArea(areaPoints); } break; } } } } } } }
void ConnectPoints() { var connectPointMap = new Dictionary <RiverPoint, FieldConnectPoint>(); FieldConnectPoint point = ToFieldConnectPoint(rootPoint); point.Index = 0; points.Add(point); connectPointMap.Add(rootPoint, point); leftRightPoints.Add(new Vector3[] { vertices[0], vertices[1] }); pointLevels.Add(0); List <RiverPoint> nextPoints = rootPoint.NextPoints; for (int i0 = 0; i0 < nextPoints.Count; ++i0) { ConnectPointsRecursive(point, nextPoints[i0], connectPointMap, 1); } }
Dictionary <Vector2Int, List <FieldConnectPoint> > CreatePointsMap(List <FieldConnectPoint> points, float chunkSize) { var pointsMap = new Dictionary <Vector2Int, List <FieldConnectPoint> >(); for (int i0 = 0; i0 < points.Count; ++i0) { FieldConnectPoint point = points[i0]; Vector2Int chunk = GetChunk(point.Position, chunkSize); List <FieldConnectPoint> pointsInChunk; if (pointsMap.TryGetValue(chunk, out pointsInChunk) == false) { pointsInChunk = new List <FieldConnectPoint>(); pointsMap.Add(chunk, pointsInChunk); } pointsInChunk.Add(point); } return(pointsMap); }
void ConnectPointsRecursive(FieldConnectPoint prevPoint, RiverPoint currentPoint, Dictionary <RiverPoint, FieldConnectPoint> connectPointMap, int pointLevel) { if (connectPointMap.TryGetValue(currentPoint, out FieldConnectPoint point) == false) { point = ToFieldConnectPoint(currentPoint); point.Index = points.Count; points.Add(point); connectPointMap.Add(currentPoint, point); int leftIndex = leftRightPoints.Count * 2; leftRightPoints.Add(new Vector3[] { vertices[leftIndex], vertices[leftIndex + 1] }); if (point.Index - prevPoint.Index > 1) { leftRightPoints.Add(new Vector3[] { vertices[leftIndex + 2], vertices[leftIndex + 3] }); pointLevels.Add(pointLevel - 1); pointLevels.Add(pointLevel); } else { pointLevels.Add(pointLevel); } prevPoint.SetConnection(point); point.SetConnection(prevPoint); List <RiverPoint> nextPoints = currentPoint.NextPoints; for (int i0 = 0; i0 < nextPoints.Count; ++i0) { ConnectPointsRecursive(point, nextPoints[i0], connectPointMap, pointLevel + 1); } } else { prevPoint.SetConnection(point); point.SetConnection(prevPoint); int leftIndex = leftRightPoints.Count * 2; leftRightPoints.Add(new Vector3[] { vertices[leftIndex], vertices[leftIndex + 1] }); pointLevels.Add(pointLevel); } }
bool IsExistCombination(IReadOnlyList <FieldConnectPoint> points) { bool isExist = true; for (int i0 = 0; i0 < points.Count; ++i0) { isExist = true; FieldConnectPoint point = points[i0]; HashSet <int> comb; if (combination.TryGetValue(point.Index, out comb) != false) { for (int i1 = 0; i1 < points.Count; ++i1) { if (i1 != i0) { FieldConnectPoint p = points[i1]; if (comb.Contains(p.Index) == false) { isExist = false; break; } } } if (isExist != false) { break; } } else { isExist = false; } } return(isExist); }
/** * リストの設定 * 設定したいポイントがすでにリストにあるかどうか調べて、ない場合は追加する * @param point リストに追加したいポイント */ public void SetConnection(FieldConnectPoint point) { int i0; float tmp_f; Vector3 sub; bool flg; flg = true; for (i0 = 0; i0 < ConnectionList.Count; ++i0) { sub = point.Position - ConnectionList[i0].Position; tmp_f = sub.x * sub.x + sub.z * sub.z; if (tmp_f >= 0.1f) { continue; } flg = false; break; } if (flg != false) { ConnectionList.Add(point); } }
void DetectPentagonArea(List <FieldConnectPoint> roadPoints) { for (int i0 = 0; i0 < roadPoints.Count; ++i0) { FieldConnectPoint point = roadPoints[i0]; List <FieldConnectPoint> connectedPoints = point.ConnectionList; for (int i1 = 0; i1 < connectedPoints.Count; ++i1) { FieldConnectPoint connectedPoint = connectedPoints[i1]; List <FieldConnectPoint> candidates = connectedPoint.ConnectionList; for (int i2 = i1 + 1; i2 < connectedPoints.Count; ++i2) { FieldConnectPoint connectedPoint2 = connectedPoints[i2]; List <FieldConnectPoint> candidates2 = connectedPoint2.ConnectionList; if (candidates.Contains(connectedPoint2) == false) { bool detected = false; for (int i3 = 0; i3 < candidates.Count; ++i3) { FieldConnectPoint candidate = candidates[i3]; if (candidate.Index != point.Index) { for (int i4 = 0; i4 < candidate.ConnectionList.Count; ++i4) { FieldConnectPoint candidate2 = candidate.ConnectionList[i4]; if (candidate2.Index != point.Index) { if (candidates2.Contains(candidate2) != false) { if (IsExistCombination(new[] { point, connectedPoint, candidate, candidate2 }) == false && IsExistCombination(new[] { point, connectedPoint, candidate, connectedPoint2 }) == false && IsExistCombination(new[] { point, connectedPoint, candidate2, connectedPoint2 }) == false && IsExistCombination(new[] { point, candidate, candidate2, connectedPoint2 }) == false && IsExistCombination(new[] { connectedPoint, candidate, candidate2, connectedPoint2 }) == false) { var pentagonAreaPoints = new List <FieldConnectPoint>() { point, connectedPoint, candidate, candidate2, connectedPoint2 }; if (IsExistCombination(pentagonAreaPoints) == false) { AddCombination(pentagonAreaPoints); List <FieldConnectPoint> squarePoints = ConvertPentagonToSquare(pentagonAreaPoints); AddArea(squarePoints); detected = true; break; } } } } } if (detected != false) { break; } } } } } } } }
/** * フィールドの座標リストを接続クラスに変えてリストにする */ void SetFieldPoint() { int i0, i1; FieldConnectPoint createPoint; List <FieldConnectPoint> addList; bool flg; riverConnectPointList.Clear(); roadConnectPointList.Clear(); sugorokuConnectPointList.Clear(); for (i0 = 0; i0 < fieldPointList.Count; ++i0) { for (i1 = 0; i1 < 3; ++i1) { flg = false; switch (i1) { case 0: addList = riverConnectPointList; if (fieldPointList[i0].Type == PointType.kRiver) { flg = true; } break; case 1: addList = roadConnectPointList; if (fieldPointList[i0].Type == PointType.kRoadAlongRiver || fieldPointList[i0].Type == PointType.kGridRoad || fieldPointList[i0].Type == PointType.kDistrictRoad || fieldPointList[i0].Type == PointType.kIntersectionOfGridRoadAndRoadAlongRiver || fieldPointList[i0].Type == PointType.kIntersectionOfGridRoadAndDistrictRoad || fieldPointList[i0].Type == PointType.kIntersectionOfRoadAlongRiverAndDistrictRoad) { flg = true; } break; case 2: addList = sugorokuConnectPointList; if (fieldPointList[i0].Type == PointType.kGridRoad || fieldPointList[i0].Type == PointType.kIntersectionOfGridRoadAndRoadAlongRiver || fieldPointList[i0].Type == PointType.kIntersectionOfGridRoadAndDistrictRoad) { flg = true; } break; default: addList = riverConnectPointList; flg = false; break; } if (flg != false) { createPoint = new FieldConnectPoint(); createPoint.Initialize(fieldPointList[i0].Position, fieldPointList[i0].Type); addList.Add(createPoint); } } } }
/** * ポイントのリストを元に接続の処理を行う * @param pointList ポイントクラスのリスト * @param interval 繋がる座標感の幅 * @param inOrder 順番通りに繋げるフラグ。川のように座標が順番に生成されるような時にtrueにする * @param mergeSize 頂点を融合させる時の判定サイズ * @param ofsetSize 外周からのオフセットサイズ、外周からこのサイズ分内側でのみ接続を行う * @param random 接続する確率 * @param maxNum 接続する最大数。-1の場合は判定しない */ public void SetConnection(List <FieldConnectPoint> pointList, float interval, float chunkSize, Vector2Int numChunks, bool inOrder = false, float random = 1f, int maxNum = -1) { int index; float checkTheta = 0.707f; var min = new float[4]; var no = new int[4]; float itv = interval * interval; int randomCount = 0; float chunkSizeInternal = chunkSize; Vector2Int numChunksInternal = numChunks; if (interval <= chunkSize * 0.5f) { chunkSizeInternal = chunkSize * 0.5f; numChunksInternal *= 2; } var pointsMap = CreatePointsMap(pointList, chunkSizeInternal); var direction = new Vector3[4]; direction[0] = Vector3.forward; direction[1] = Vector3.back; direction[2] = Vector3.right; direction[3] = Vector3.left; for (int i0 = 0; i0 < pointList.Count; ++i0) { FieldConnectPoint currentPoint = pointList[i0]; List <Vector2Int> chunks = GetCandidateChunks(currentPoint.Position, chunkSizeInternal, numChunksInternal, interval); var targetPoints = new List <FieldConnectPoint>(); for (int i1 = 0; i1 < chunks.Count; ++i1) { if (pointsMap.TryGetValue(chunks[i1], out List <FieldConnectPoint> points) != false) { targetPoints.AddRange(points); } } if (maxNum >= 0 && maxNum <= randomCount) { /* ランダムで作る最大数に達しているので処理を終わる */ return; } float rand = (float)randomSystem.NextDouble(); if (rand > random) { /* ランダムに判定しない */ continue; } min[0] = itv; min[1] = itv; min[2] = itv; min[3] = itv; no[0] = -1; no[1] = -1; no[2] = -1; no[3] = -1; bool orderFlag = false; int count = currentPoint.ConnectionList.Count; if (count < 4) { for (int i1 = 0; i1 < targetPoints.Count; ++i1) { if (inOrder != false && count > 0) { /* 順番通りの場合は次の座標と判断する */ if (orderFlag == false) { if (i0 < i1) { break; } i1 = i0 + 1; if (i1 >= targetPoints.Count) { break; } orderFlag = true; } } if (i0 == i1) { /* 同じものは判定しない */ continue; } if (currentPoint.Type == PointType.kRoadAlongRiver) { if (targetPoints[i1].Type == PointType.kRoadAlongRiver) { /* 川沿いの道路は川と同じように前後の座標と結ぶようにする */ if (i1 != i0 + 1) { continue; } } else { /* 川沿いから繋ぐ場合は、川沿いの道路とだけ接続する */ continue; } } Vector3 sub = Vector3.zero; sub.x = targetPoints[i1].Position.x - currentPoint.Position.x; sub.z = targetPoints[i1].Position.z - currentPoint.Position.z; float length = sub.x * sub.x + sub.z * sub.z; if (length > itv) { /* 距離が離れているものは判定しない */ continue; } sub = sub.normalized; bool flg = false; for (int i2 = 0; i2 < 4; ++i2) { float theta = sub.x * direction[i2].x + sub.z * direction[i2].z; if (theta <= checkTheta) { /* 角度の条件を満たしていない */ continue; } if (min[i2] <= length) { /* すでに設定しているものより遠い */ continue; } min[i2] = length; no[i2] = i1; flg = true; } if (flg != false) { ++count; } if (inOrder != false) { if (orderFlag != false) { i1 = targetPoints.Count; } } } for (int i1 = 0; i1 < direction.Length; ++i1) { if (no[i1] < 0) { /* この方向に繋げる座標が無かった */ continue; } index = no[i1]; currentPoint.SetConnection(targetPoints[index]); targetPoints[index].SetConnection(currentPoint); } ++randomCount; } } /* 孤立している点は削除する */ for (int i0 = pointList.Count - 1; i0 >= 0; --i0) { if (pointList[i0].ConnectionList.Count == 0) { pointList.RemoveAt(i0); } } }