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); }
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); } }
public static Vector3Int Normal(this CornerDir dir) { return(new Vector3Int(dir.X(), dir.Y(), dir.Z())); }
public static int Ordinal(this CornerDir dir) { return(dir.GetAttribute <CornerDirAttribute>().Ordinal); }
public static int Z(this CornerDir dir) { return(dir.GetAttribute <CornerDirAttribute>().Z); }