Esempio n. 1
0
        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);
            }
        }
        /**
         * ポイントのリストを元に接続の処理を行う
         * @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);
                }
            }
        }