Esempio n. 1
0
        public void Update()
        {
            var segment   = GetSegment();
            var segmentId = GetSegmentId();

            Vector3 leftPos;
            Vector3 rightPos;
            Vector3 leftDir;
            Vector3 rightDir;

            if (IsStartSide)
            {
                segment.CalculateCorner(segmentId, true, true, true, out leftPos, out leftDir, out _);
                segment.CalculateCorner(segmentId, true, true, false, out rightPos, out rightDir, out _);
            }
            else
            {
                segment.CalculateCorner(segmentId, true, false, true, out leftPos, out leftDir, out _);
                segment.CalculateCorner(segmentId, true, false, false, out rightPos, out rightDir, out _);
            }

            CornerDir   = (rightPos - leftPos).normalized;
            CornerAngle = CornerDir.AbsoluteAngle();

            NormalDir   = NormalSign * (leftDir + rightDir).normalized;
            NormalAngle = NormalDir.AbsoluteAngle();

            var angle = Vector3.Angle(NormalDir, CornerDir);

            CornerAndNormalAngle = (angle > 90 ? 180 - angle : angle) * Mathf.Deg2Rad;
            TranformCoef         = Mathf.Sin(CornerAndNormalAngle);

            Position = (leftPos + rightPos) / 2f;

            RoadHalfWidth  = segment.Info.m_halfWidth - segment.Info.m_pavementWidth;
            FirstPointSide = GetPosition(-RoadHalfWidth);
            LastPointSide  = GetPosition(RoadHalfWidth);
            Line           = new StraightTrajectory(FirstPointSide, LastPointSide);
        }
Esempio n. 2
0
        public void GenerateShape(float divDuration, float divSize, DateTime zeroTime, Transform parent,
                                  Material baseMat)
        {
            DateTime now = DateTime.Now;

            List <Vector3> verts = new List <Vector3>();
            List <int>     tris  = new List <int>();

            pointList = new List <Coord2>();

            if (shape)
            {
                Destroy(shape.gameObject);
            }

            if (guideSpan != SpanAlignment.None)
            {
                labels.DestroyAll();
            }

            GameObject shapeObject = new GameObject(name);

            shape = shapeObject.transform;
            shapeObject.transform.parent = parent;
            // Debug.Log( "Generated color for " + name + ": " + color );

            LineRenderer edgePrefabToUse = instance.edgePrefab;

            if (guideSpan == SpanAlignment.Months)
            {
                edgePrefabToUse = instance.monthEdgePrefab;
            }
            if (guideSpan == SpanAlignment.Years)
            {
                edgePrefabToUse = instance.yearEdgePrefab;
            }
            if (guideSpan == SpanAlignment.Decades)
            {
                edgePrefabToUse = instance.decadeEdgePrefab;
            }

            if (guideSpan != SpanAlignment.None)
            {
                blocks.Clear();
            }

            switch (guideSpan)
            {
            case SpanAlignment.Months: {
                DateTime currStartDate = instance.mapStartTime;

                while (currStartDate <= now)
                {
                    DateTime endDate = currStartDate.AddMonths(1).AddDays(1 - currStartDate.Day);
                    if (endDate > now)
                    {
                        endDate = now;
                    }
                    blocks.Add(new TimeBlock(currStartDate, endDate, currStartDate.Month.ToString()));
                    if (endDate == now)
                    {
                        break;
                    }
                    currStartDate = endDate;
                }
            } break;

            case SpanAlignment.Years: {
                DateTime currStartDate = calendarAligned ? instance.mapStartTime : instance.lifeStartTime;
                int      age           = 0;

                while (currStartDate <= now)
                {
                    DateTime endDate = currStartDate.AddYears(1);
                    if (calendarAligned)
                    {
                        endDate = endDate.AddDays(1 - endDate.DayOfYear);
                    }
                    if (endDate > now)
                    {
                        endDate = now;
                    }
                    blocks.Add(new TimeBlock(currStartDate, endDate,
                                             (calendarAligned ? currStartDate.Year : age).ToString()));
                    if (endDate == now)
                    {
                        break;
                    }
                    currStartDate = endDate;
                    age++;
                }
            } break;

            case SpanAlignment.Decades: {
                DateTime currStartDate = calendarAligned ? instance.mapStartTime : instance.lifeStartTime;
                int      age           = 0;

                while (currStartDate <= now)
                {
                    DateTime endDate = currStartDate.AddYears(10);
                    if (calendarAligned)
                    {
                        endDate = new DateTime(endDate.Year - endDate.Year % 10, 1, 1);
                    }
                    if (endDate > now)
                    {
                        endDate = now;
                    }
                    blocks.Add(new TimeBlock(currStartDate, endDate,
                                             (calendarAligned ? currStartDate.Year - currStartDate.Year % 10 : age) + "s"));
                    if (endDate == now)
                    {
                        break;
                    }
                    currStartDate = endDate;
                    age          += 10;
                }
            } break;
            }

            foreach (var block in blocks)
            {
                int startDiv = (int)(block.startTime.Subtract(zeroTime).TotalDays / divDuration);
                int endDiv   = (int)(block.endTime.Subtract(zeroTime).TotalDays / divDuration);
                bool[,]                   blockPoints = new bool[size, size];
                bool[,]                   vertLines   = new bool[size + 1, size + 1];
                bool[,]                   horizLines  = new bool[size + 1, size + 1];
                List <Coord2>            blockPointList = new List <Coord2>();
                HashSet <Coord2>         coveredPoints  = new HashSet <Coord2>();
                Dictionary <Coord2, int> rectSizes      = new Dictionary <Coord2, int>();

                /*
                 * bool debug = Random.value < 0.1f;
                 * /*/
                bool debug = false;
                //*/

                // Debug.Log( "Drawing shape for " + name + "; start: " + block.startTime + "; startDiv: " + startDiv
                //               + "; end: " + block.endTime + "; endDiv: " + endDiv );

                for (int i = startDiv; i < endDiv; i++)
                {
                    int[] originCoords = HilbertCurve.IntToHilbert(i, 2);

                    points     [originCoords[0], originCoords[1]] = true;
                    blockPoints[originCoords[0], originCoords[1]] = true;
                    blockPointList.Add(new Coord2(originCoords[0], originCoords[1]));
                    pointList.Add(new Coord2(originCoords[0], originCoords[1]));
                }

                blockPointList = blockPointList.OrderByDescending(p =>
                                                                  Enumerable.Range(0, 8)
                                                                  .Select(n => (int)Mathf.Pow(2, n))
                                                                  .Where(n => p.x % n == 0 && p.y % n == 0)
                                                                  .Max()).ToList();

                if (debug)
                {
                    Debug.Log("points in block: " + Utils.PrintVals(blockPointList.ToArray(), false, true));
                }

                foreach (var point in blockPointList)
                {
                    if (coveredPoints.Contains(point))
                    {
                        continue;
                    }
                    //coveredPoints.Add( point );
                    int         rectSize = 1;
                    Coord2Range range    = new Coord2Range(point);

                    for (rectSize = 1; rectSize < 256; rectSize *= 2)
                    {
                        if (point.x % rectSize != 0 || point.y % rectSize != 0)
                        {
                            break;
                        }
                        if (point.x + rectSize > size || point.y + rectSize > size)
                        {
                            break;
                        }

                        var newRange = new Coord2Range(point, point + Coord2.one * (rectSize - 1));
                        if (newRange.Any(p => !blockPoints[p.x, p.y] || coveredPoints.Contains(p)))
                        {
                            break;
                        }

                        range = newRange;

                        if (debug)
                        {
                            Debug.Log("rect size: " + rectSize + "; range: " + range + "; covered by range: "
                                      + Utils.PrintVals(range.ToArray(), false, true));
                        }
                    }
                    rectSize /= 2;
                    foreach (var covered in range)
                    {
                        coveredPoints.Add(covered);
                    }
                    if (debug)
                    {
                        Debug.Log("covered points is now: " + Utils.PrintVals(coveredPoints.ToArray(), false, true));
                    }
                    rectSizes[point] = rectSize;
                }

                if (debug)
                {
                    Debug.Log("Rect sizes for block in " + name + ":\n"
                              + string.Join("\n", rectSizes.Select(r => r.Key + ": " + r.Value).ToArray()));
                }

                foreach (var rect in rectSizes)
                {
                    int     vertInd = verts.Count;
                    Vector3 origin  = new Vector3(rect.Key.x, instance.elementMeshY, rect.Key.y) * divSize;

                    verts.Add(origin);
                    verts.Add(origin + Vector3.forward * divSize * rect.Value);
                    verts.Add(origin + Vector3.right * divSize * rect.Value);
                    verts.Add(origin + new Vector3(divSize, 0.0f, divSize) * rect.Value);

                    tris.Add(vertInd);
                    tris.Add(vertInd + 1);
                    tris.Add(vertInd + 3);
                    tris.Add(vertInd);
                    tris.Add(vertInd + 3);
                    tris.Add(vertInd + 2);
                }

                // add corners
                CornerDir[,] corners = new CornerDir[size + 1, size + 1];

                // add individual edge segments
                for (int x = 0; x < size; x++)
                {
                    for (int y = 0; y < size; y++)
                    {
                        if (!blockPoints[x, y])
                        {
                            continue;
                        }

                        if (((x == 0 || !blockPoints[x - 1, y]) && (y == 0 || !blockPoints[x, y - 1])) ||
                            ((x > 0 && blockPoints[x - 1, y]) && (y > 0 && blockPoints[x, y - 1])))
                        {
                            corners[x, y] = CornerDir.LowerLeft;
                        }

                        if (((x == 0 || !blockPoints[x - 1, y]) && (y == size - 1 || !blockPoints[x, y + 1])) ||
                            ((x > 0 && blockPoints[x - 1, y]) && (y < size - 1 && blockPoints[x, y + 1])))
                        {
                            corners[x, y + 1] = CornerDir.UpperLeft;
                        }

                        if (((x == size - 1 || !blockPoints[x + 1, y]) && (y == size - 1 || !blockPoints[x, y + 1])) ||
                            ((x < size - 1 && blockPoints[x + 1, y]) && (y < size - 1 && blockPoints[x, y + 1])))
                        {
                            corners[x + 1, y + 1] = CornerDir.UpperRight;
                        }

                        if (((x == size - 1 || !blockPoints[x + 1, y]) && (y == 0 || !blockPoints[x, y - 1])) ||
                            ((x < size - 1 && blockPoints[x + 1, y]) && (y > 0 && blockPoints[x, y - 1])))
                        {
                            corners[x + 1, y] = CornerDir.LowerRight;
                        }

                        if (x == 0 || !blockPoints[x - 1, y])
                        {
                            vertLines[x, y] = true;
                        }
                        if (x == size - 1 || !blockPoints[x + 1, y])
                        {
                            vertLines[x + 1, y] = true;
                        }

                        if (y == 0 || !blockPoints[x, y - 1])
                        {
                            horizLines[x, y] = true;
                        }
                        if (y == size - 1 || !blockPoints[x, y + 1])
                        {
                            horizLines[x, y + 1] = true;
                        }
                    }
                }

                // combine edge segments into lines
                List <LineSpan> spans = new List <LineSpan>();

                // vertical lines first
                for (int x = 0; x <= size; x++)
                {
                    for (int y = 0; y <= size; y++)
                    {
                        if (!vertLines[x, y])
                        {
                            continue;
                        }

                        int startY = y;
                        while (vertLines[x, y])
                        {
                            y++;
                        }

                        spans.Add(new LineSpan(x, startY, x, y));
                    }
                }

                for (int y = 0; y <= size; y++)
                {
                    for (int x = 0; x <= size; x++)
                    {
                        if (!horizLines[x, y])
                        {
                            continue;
                        }

                        int startX = x;
                        while (horizLines[x, y])
                        {
                            x++;
                        }

                        spans.Add(new LineSpan(startX, y, x, y));
                    }
                }

                //Debug.Log( name + " block has " + spans.Count + " line spans" );

                if (spans.Count == 0)
                {
                    continue;
                }
                List <Coord2> lineCoords = new List <Coord2>();
                LineSpan      currSpan   = spans.Random();
                spans.Remove(currSpan);
                LineSpan nextSpan = null;
                Coord2   currEnd  = currSpan.end;
                lineCoords.Add(currSpan.start);
                lineCoords.Add(currSpan.end);

                // Debug.Log( "currSpan is " + currEnd + "; all other spans:\n"
                //               + Utils.PrintVals( spans.ToArray(), false, true ) );

                // foreach (var span in spans) {

                //    Debug.Log( "Match " + span + ": " + (span.start == currEnd || span.end == currEnd) );
                // }

                while ((nextSpan = spans.FirstOrDefault(s => s.start == currEnd || s.end == currEnd)) != null)
                {
                    currEnd = nextSpan.start == currEnd ? nextSpan.end : nextSpan.start;
                    spans.Remove(nextSpan);
                    currSpan = nextSpan;
                    lineCoords.Add(currEnd);
                }

                LineRenderer lineRenderer = Instantiate(edgePrefabToUse, shapeObject.transform);
                lineRenderer.positionCount = lineCoords.Count;
                float yPosition = guideSpan == SpanAlignment.None ? instance.elementEdgeY : instance.guideEdgeY;
                lineRenderer.widthMultiplier *= divSize * 0.333f;
                float cornerShift = lineRenderer.widthMultiplier * 0.5f;
                // Vector3[] shunkLineVerts = instance.ShrinkPath( lineVerts.Select( c => ((Vector3) (Vector2) c) * divSize ).ToArray(),
                //                                                 lineRenderer.widthMultiplier * 0.5f );
                Vector3[] lineVerts = lineCoords.Select(coord => {
                    var cornerDir = corners[coord.x, coord.y];
                    Vector3 vert  = new Vector3(coord.x * divSize, yPosition, coord.y * divSize);
                    if (guideSpan != SpanAlignment.None)
                    {
                        return(vert);
                    }
                    if (cornerDir == CornerDir.UpperLeft || cornerDir == CornerDir.LowerLeft)
                    {
                        vert.x += cornerShift;
                    }
                    else
                    {
                        vert.x -= cornerShift;
                    }
                    if (cornerDir == CornerDir.UpperLeft || cornerDir == CornerDir.UpperRight)
                    {
                        vert.z -= cornerShift;
                    }
                    else
                    {
                        vert.z += cornerShift;
                    }
                    return(vert);
                }).ToArray();
                lineRenderer.SetPositions(lineVerts);

                if (guideSpan == SpanAlignment.None)
                {
                    Color edgeColor = color.ShiftLuma(0.1f);
                    edgeColor.a             = 1.0f;
                    lineRenderer.startColor = lineRenderer.endColor = edgeColor;
                }
                // Debug.Log( "Generated edge color for " + name + ": " + edgeColor );

                if (guideSpan != SpanAlignment.None)
                {
                    Vector3 position = blockPointList.Select(v => new Vector3(v.x, 0.0f, v.y)).Average() * divSize
                                       + Vector3.up * instance.guideLabelY;

                    if (!block.label)
                    {
                        block.label = Instantiate(labelPrefabToUse, labelParent.transform as RectTransform);
                        //label.transform.position = position;
                        block.label.localPosition = Utils.WorldToCanvasSpace(position, labelParent.transform as RectTransform,
                                                                             block.label);
                        Text labelText = block.label.GetComponentInChildren <Text>();
                        labelText.text = block.labelString;
                        labels.Add(block.label);
                    }

                    block.label.localPosition
                        = Utils.WorldToCanvasSpace(position, labelParent.transform as RectTransform,
                                                   block.label.transform as RectTransform);
                }
            }

            if (guideSpan == SpanAlignment.None)
            {
                Mesh mesh = new Mesh();
                mesh.vertices  = verts.ToArray();
                mesh.triangles = tris.ToArray();
                mesh.RecalculateBounds();
                mesh.RecalculateNormals();
                MeshFilter meshFilter = shapeObject.AddComponent <MeshFilter>();
                meshFilter.sharedMesh = mesh;
                Material mat = new Material(baseMat);
                mat.color = color * 0.6f;
                // Debug.Log( "Applying mesh material color for " + name + ": " + color );
                MeshRenderer meshRenderer = shapeObject.AddComponent <MeshRenderer>();
                meshRenderer.sharedMaterial = mat;

                Vector3 position = pointList.Select(v => new Vector3(v.x, 0.0f, v.y)).Average() * divSize
                                   + Vector3.up * instance.elementLabelY;
                //Debug.Log( name + " average point position: " + position );
                //label.transform.position = position;
                label.localPosition = Utils.WorldToCanvasSpace(position, labelParent.transform as RectTransform,
                                                               label.transform as RectTransform);
            }
        }
Esempio n. 3
0
 public static Vector3Int Normal(this CornerDir dir)
 {
     return(new Vector3Int(dir.X(), dir.Y(), dir.Z()));
 }
Esempio n. 4
0
 public static int Ordinal(this CornerDir dir)
 {
     return(dir.GetAttribute <CornerDirAttribute>().Ordinal);
 }
Esempio n. 5
0
 public static int Z(this CornerDir dir)
 {
     return(dir.GetAttribute <CornerDirAttribute>().Z);
 }