예제 #1
0
        /// <summary>
        /// Navigate from X/Y to X/Y coordinates
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        public Ets2NavigationRoute NavigateTo(Ets2Point from, Ets2Point to)
        {
            var start = FindClosestRoadPrefab(from);
            var end = FindClosestRoadPrefab(to);

            Console.WriteLine("Navigating from " + start.ItemUID.ToString("X16") + " to " + end.ItemUID.ToString("X16"));
            // Look up pre-fab closest by these 2 points
            return new Ets2NavigationRoute(start,end, from, to, this);
        }
예제 #2
0
 public  Ets2Item FindClosestRoadPrefab(Ets2Point location)
 {
     // Find road or prefab closest by
     var closestPrefab =
         Items.Values.Where(x => x.HideUI==false && x.Type == Ets2ItemType.Prefab && x.Prefab != null && x.Prefab.Curves.Any())
             .OrderBy(x => Math.Sqrt(Math.Pow(location.X - x.PrefabNode.X, 2) + Math.Pow(location.Z - x.PrefabNode.Z, 2)))
             .FirstOrDefault();
     return closestPrefab;
 }
예제 #3
0
        /// <summary>
        /// Navigate from X/Y to X/Y coordinates
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        public Ets2NavigationRoute NavigateTo(Ets2Point from, Ets2Point to)
        {
            var start = FindClosestRoadPrefab(from);
            var end   = FindClosestRoadPrefab(to);

            Console.WriteLine("Navigating from " + start.ItemUID.ToString("X16") + " to " + end.ItemUID.ToString("X16"));
            // Look up pre-fab closest by these 2 points
            return(new Ets2NavigationRoute(start, end, from, to, this));
        }
예제 #4
0
        public Ets2Item FindClosestRoadPrefab(Ets2Point location)
        {
            // Find road or prefab closest by
            var closestPrefab =
                Items.Values.Where(x => x.HideUI == false && x.Type == Ets2ItemType.Prefab && x.Prefab != null && x.Prefab.Curves.Any())
                .OrderBy(x => Math.Sqrt(Math.Pow(location.X - x.PrefabNode.X, 2) + Math.Pow(location.Z - x.PrefabNode.Z, 2)))
                .FirstOrDefault();

            return(closestPrefab);
        }
예제 #5
0
        public float DistanceTo(Ets2Point pt)
        {
            if (pt == null) return float.MaxValue;
            var dx = pt.X - X;
            var dy = pt.Z - Z;

            var dst = (float) Math.Sqrt(dx * dx + dy * dy);

            return dst;
        }
예제 #6
0
        /// <summary>
        /// Navigate to city from X/Y point
        /// </summary>
        /// <param name="from"></param>
        /// <param name="city"></param>
        public Ets2NavigationRoute NavigateTo(Ets2Point from, string city)
        {
            if (Cities.ContainsKey(city) == false)
                return null;

            var cityPoint = Cities[city].StartNode.Point;

            var start = FindClosestRoadPrefab(from);
            var end = FindClosestRoadPrefab(cityPoint);

            return new Ets2NavigationRoute(start, end, from, null, this);
        }
예제 #7
0
        public Ets2NavigationRoute(Ets2Item start, Ets2Item end, Ets2Point from, Ets2Point to, Ets2Mapper mapper)
        {
            Start  = start;
            End    = end;
            From   = from;
            To     = to;
            Mapper = mapper;

            if (Start != End)
            {
                ThreadPool.QueueUserWorkItem(FindRoute);
            }
        }
예제 #8
0
        public Ets2NavigationRoute(Ets2Item start, Ets2Item end, Ets2Point from, Ets2Point to, Ets2Mapper mapper)
        {
            Start = start;
            End = end;
            From = from;
            To = to;
            Mapper = mapper;

            if (Start != End)
            {
                ThreadPool.QueueUserWorkItem(FindRoute);
            }
        }
예제 #9
0
        public float DistanceTo(Ets2Point pt)
        {
            if (pt == null)
            {
                return(float.MaxValue);
            }
            var dx = pt.X - X;
            var dy = pt.Z - Z;

            var dst = (float)Math.Sqrt(dx * dx + dy * dy);

            return(dst);
        }
예제 #10
0
        /// <summary>
        /// Navigate to city from X/Y point
        /// </summary>
        /// <param name="from"></param>
        /// <param name="city"></param>
        public Ets2NavigationRoute NavigateTo(Ets2Point from, string city)
        {
            if (Cities.ContainsKey(city) == false)
            {
                return(null);
            }

            var cityPoint = Cities[city].StartNode.Point;

            var start = FindClosestRoadPrefab(from);
            var end   = FindClosestRoadPrefab(cityPoint);

            return(new Ets2NavigationRoute(start, end, from, null, this));
        }
예제 #11
0
        public void GenerateRoadPolygon(int steps)
        {
            if (RoadPolygons == null)
            {
                RoadPolygons = new Ets2Point[0];
            }

            if (RoadPolygons != null && RoadPolygons.Count() == steps)
            {
                return;
            }

            if (StartNode == null || EndNode == null)
            {
                return;
            }

            if (Type != Ets2ItemType.Road)
            {
                return;
            }

            var ps = new Ets2Point[steps];

            var sx = StartNode.X;
            var ex = EndNode.X;
            var sz = StartNode.Z;
            var ez = EndNode.Z;

            var radius = (float)Math.Sqrt((sx - ex) * (sx - ex) + (sz - ez) * (sz - ez));

            var tangentSX = (float)Math.Cos(-StartNode.Yaw) * radius;
            var tangentEX = (float)Math.Cos(-EndNode.Yaw) * radius;
            var tangentSZ = (float)Math.Sin(-StartNode.Yaw) * radius;
            var tangentEZ = (float)Math.Sin(-EndNode.Yaw) * radius;

            for (int k = 0; k < steps; k++)
            {
                var s = (float)k / (float)(steps - 1);
                var x = (float)Ets2CurveHelper.Hermite(s, sx, ex, tangentSX, tangentEX);
                var z = (float)Ets2CurveHelper.Hermite(s, sz, ez, tangentSZ, tangentEZ);

                ps[k] = new Ets2Point(x, 0, z, 0);
            }

            RoadPolygons = ps;
        }
예제 #12
0
        public IEnumerable <Ets2Point> GeneratePolygonForRoute(Ets2PrefabRoute route, Ets2Node node, int nodeOr)
        {
            List <Ets2Point> p = new List <Ets2Point>();

            if (route == null || route.Route == null)
            {
                return(p);
            }

            /*
             * yaw -= this.Nodes[nodeOr].Yaw;
             * yaw += Math.PI/2;
             */
            var xOr = node.X;
            var yOr = node.Z;
            var yaw = node.Yaw - this.Nodes[nodeOr].Yaw + Math.PI / 2;

            foreach (var curve in route.Route)
            {
                var srx = curve.StartX - this.Nodes[nodeOr].X;
                var erx = curve.EndX - this.Nodes[nodeOr].X;
                var srz = curve.StartZ - this.Nodes[nodeOr].Z;
                var erz = curve.EndZ - this.Nodes[nodeOr].Z;

                var sr = (float)Math.Sqrt(srx * srx + srz * srz);
                var er = (float)Math.Sqrt(erx * erx + erz * erz);

                var ans = yaw - Math.Atan2(srz, srx);
                var ane = yaw - Math.Atan2(erz, erx);

                var sx = xOr - sr * (float)Math.Sin(ans);
                var ex = xOr - er * (float)Math.Sin(ane);
                var sz = yOr - sr * (float)Math.Cos(ans);
                var ez = yOr - er * (float)Math.Cos(ane);

                // TODO: Temporary linear interpolation
                // TODO: Interpolate heading & Y value
                var ps = new Ets2Point[2];
                ps[0] = new Ets2Point(sx, node.Y, sz, (float)ans);
                ps[1] = new Ets2Point(ex, node.Y, ez, (float)ane);

                p.AddRange(ps);
            }

            return(p);
        }
예제 #13
0
        /// <summary>
        /// Generate road curves for a specific lane. The curve is generated with [steps]
        /// nodes and positioned left or right from the road's middle point.
        /// Additionally, each extra lane is shifted 4.5 game units outward.
        /// </summary>
        /// <param name="steps"></param>
        /// <param name="leftlane"></param>
        /// <param name="lane"></param>
        /// <returns></returns>
        public IEnumerable <Ets2Point> GenerateRoadCurve(int steps, bool leftlane, int lane)
        {
            var ps = new Ets2Point[steps];

            var sx = StartNode.X;
            var ex = EndNode.X;
            var sz = StartNode.Z;
            var ez = EndNode.Z;

            if (steps == 2)
            {
                sx += (float)Math.Sin(-StartNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f);
                sz += (float)Math.Cos(-StartNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f);

                ex += (float)Math.Sin(-EndNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f);
                ez += (float)Math.Cos(-EndNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f);

                ps[0] = new Ets2Point(sx, 0, sz, StartNode.Yaw);
                ps[1] = new Ets2Point(ex, 0, ez, EndNode.Yaw);
                return(ps);
            }


            var radius = (float)Math.Sqrt((sx - ex) * (sx - ex) + (sz - ez) * (sz - ez));

            var tangentSX = (float)Math.Cos(-StartNode.Yaw) * radius;
            var tangentEX = (float)Math.Cos(-EndNode.Yaw) * radius;
            var tangentSZ = (float)Math.Sin(-StartNode.Yaw) * radius;
            var tangentEZ = (float)Math.Sin(-EndNode.Yaw) * radius;

            for (int k = 0; k < steps; k++)
            {
                var s   = (float)k / (float)(steps - 1);
                var x   = (float)Ets2CurveHelper.Hermite(s, sx, ex, tangentSX, tangentEX);
                var z   = (float)Ets2CurveHelper.Hermite(s, sz, ez, tangentSZ, tangentEZ);
                var tx  = (float)Ets2CurveHelper.HermiteTangent(s, sx, ex, tangentSX, tangentEX);
                var ty  = (float)Ets2CurveHelper.HermiteTangent(s, sz, ez, tangentSZ, tangentEZ);
                var yaw = (float)Math.Atan2(ty, tx);
                x    += (float)Math.Sin(-yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f);
                z    += (float)Math.Cos(-yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f);
                ps[k] = new Ets2Point(x, 0, z, yaw);
            }

            return(ps);
        }
예제 #14
0
        public IEnumerable<Ets2Point> GeneratePolygonForRoute(Ets2PrefabRoute route, Ets2Node node,  int nodeOr)
        {
            List<Ets2Point> p = new List<Ets2Point>();

            if (route == null || route.Route == null)
            return p;

            /*
            yaw -= this.Nodes[nodeOr].Yaw;
            yaw += Math.PI/2;
            */
            var xOr = node.X;
            var yOr = node.Z;
            var yaw = node.Yaw - this.Nodes[nodeOr].Yaw + Math.PI / 2;

            foreach (var curve in route.Route)
            {
                var srx = curve.StartX - this.Nodes[nodeOr].X;
                var erx = curve.EndX - this.Nodes[nodeOr].X;
                var srz = curve.StartZ - this.Nodes[nodeOr].Z;
                var erz = curve.EndZ - this.Nodes[nodeOr].Z;

                var sr = (float) Math.Sqrt(srx*srx + srz*srz);
                var er = (float) Math.Sqrt(erx*erx + erz*erz);

                var ans = yaw - Math.Atan2(srz, srx);
                var ane = yaw - Math.Atan2(erz, erx);

                var sx = xOr - sr*(float) Math.Sin(ans);
                var ex = xOr - er*(float) Math.Sin(ane);
                var sz = yOr - sr*(float) Math.Cos(ans);
                var ez = yOr - er*(float) Math.Cos(ane);

                // TODO: Temporary linear interpolation
                // TODO: Interpolate heading & Y value
                var ps = new Ets2Point[2];
                ps[0] = new Ets2Point(sx, node.Y, sz,(float) ans);
                ps[1] = new Ets2Point(ex, node.Y, ez, (float)ane);

                p.AddRange(ps);
            }

            return p;
        }
예제 #15
0
 /// <summary>
 /// Navigate to city company from X/Y point
 /// </summary>
 /// <param name="from"></param>
 /// <param name="city"></param>
 /// <param name="company"></param>
 public Ets2NavigationRoute NavigateTo(Ets2Point from, string city, string company)
 {
     throw new NotImplementedException();
 }
예제 #16
0
 /// <summary>
 /// Navigate to city company from X/Y point
 /// </summary>
 /// <param name="from"></param>
 /// <param name="city"></param>
 /// <param name="company"></param>
 public Ets2NavigationRoute NavigateTo(Ets2Point from, string city, string company)
 {
     throw new NotImplementedException();
 }
예제 #17
0
 public bool CloseTo(Ets2Point pt)
 {
     return DistanceTo(pt) <= 2f;
 }
예제 #18
0
 public bool CloseTo(Ets2Point pt)
 {
     return(DistanceTo(pt) <= 2f);
 }
예제 #19
0
        public IEnumerable <IEnumerable <Ets2Point> > GeneratePolygonCurves(Ets2Node node, int nodeOr)
        {
            var ks = new List <IEnumerable <Ets2Point> >();

            var steps = 16;

            if (nodeOr >= this.Nodes.Count)
            {
                nodeOr = 0;
            }
            if (Nodes.Any() == false)
            {
                return(ks);
            }

            var xOr = node.X;
            var yOr = node.Z;
            var yaw = node.Yaw - this.Nodes[nodeOr].Yaw + Math.PI / 2;

            foreach (var curve in Curves)
            {
                var ps = new Ets2Point[steps];

                var srx = curve.StartX - this.Nodes[nodeOr].X;
                var erx = curve.EndX - this.Nodes[nodeOr].X;
                var srz = curve.StartZ - this.Nodes[nodeOr].Z;
                var erz = curve.EndZ - this.Nodes[nodeOr].Z;

                var sr = (float)Math.Sqrt(srx * srx + srz * srz);
                var er = (float)Math.Sqrt(erx * erx + erz * erz);

                var ans = yaw - Math.Atan2(srz, srx);
                var ane = yaw - Math.Atan2(erz, erx);

                var sx = xOr - sr * (float)Math.Sin(ans);
                var ex = xOr - er * (float)Math.Sin(ane);
                var sz = yOr - sr * (float)Math.Cos(ans);
                var ez = yOr - er * (float)Math.Cos(ane);
                // TODO: Temporary linear interpolation
                // TODO: Interpolate heading & Y value
                ps    = new Ets2Point[2];
                ps[0] = new Ets2Point(sx, 0, sz, 0);
                ps[1] = new Ets2Point(ex, 0, ez, 0);
                ks.Add(ps);

                /*
                 * var tangentSX = (float)Math.Cos(ans) * curve.Length;
                 * var tangentEX = (float)Math.Cos(ane) * curve.Length;
                 * var tangentSY = (float)Math.Sin(ans) * curve.Length;
                 * var tangentEY = (float)Math.Sin(ane) * curve.Length;
                 *
                 * for (int k = 0; k < steps; k++)
                 * {
                 *  var s = (float)k / (float)steps;
                 *  var x = (float)Ets2CurveHelper.Hermite(s, sx, ex, tangentSX, tangentEX);
                 *  var z = (float)Ets2CurveHelper.Hermite(s, sz, ez, tangentSY, tangentEY);
                 *  ps[k] = new Ets2Point(x, 0, z, 0);
                 * }
                 *
                 * ks.Add(ps);
                 */
            }
            return(ks);
        }
예제 #20
0
        public IEnumerable<IEnumerable<Ets2Point>> GeneratePolygonCurves(Ets2Node node, int nodeOr)
        {
            var ks = new List<IEnumerable<Ets2Point>>();

            var steps = 16;
            
            if (nodeOr >= this.Nodes.Count)
                nodeOr = 0;
            if (Nodes.Any() == false)
                return ks;

            var xOr = node.X;
            var yOr = node.Z;
            var yaw = node.Yaw - this.Nodes[nodeOr].Yaw + Math.PI/2;

            foreach (var curve in Curves)
            {
                var ps = new Ets2Point[steps];

                var srx = curve.StartX - this.Nodes[nodeOr].X;
                var erx = curve.EndX - this.Nodes[nodeOr].X;
                var srz = curve.StartZ - this.Nodes[nodeOr].Z;
                var erz = curve.EndZ - this.Nodes[nodeOr].Z;

                var sr = (float) Math.Sqrt(srx * srx + srz * srz);
                var er = (float)Math.Sqrt(erx * erx + erz * erz);

                var ans = yaw - Math.Atan2(srz,srx);
                var ane = yaw - Math.Atan2(erz, erx);

                var sx = xOr - sr * (float)Math.Sin(ans);
                var ex = xOr - er * (float)Math.Sin(ane);
                var sz = yOr - sr * (float)Math.Cos(ans);
                var ez = yOr - er * (float)Math.Cos(ane);
                // TODO: Temporary linear interpolation
                // TODO: Interpolate heading & Y value
                ps = new Ets2Point[2];
                ps[0] = new Ets2Point(sx, 0, sz, 0);
                ps[1] = new Ets2Point(ex, 0, ez, 0);
                ks.Add(ps);
                
                /*
                var tangentSX = (float)Math.Cos(ans) * curve.Length;
                var tangentEX = (float)Math.Cos(ane) * curve.Length;
                var tangentSY = (float)Math.Sin(ans) * curve.Length;
                var tangentEY = (float)Math.Sin(ane) * curve.Length;

                for (int k = 0; k < steps; k++)
                {
                    var s = (float)k / (float)steps;
                    var x = (float)Ets2CurveHelper.Hermite(s, sx, ex, tangentSX, tangentEX);
                    var z = (float)Ets2CurveHelper.Hermite(s, sz, ez, tangentSY, tangentEY);
                    ps[k] = new Ets2Point(x, 0, z, 0);
                }

                ks.Add(ps);
                */
            }
            return ks;
        }
예제 #21
0
        public void Render(Graphics g, Rectangle clip, float baseScale, Ets2Point point)
        {
            _clip = clip;

            g.FillRectangle(Palette.Background, new Rectangle(0,0,clip.X+clip.Width, clip.Y+clip.Height));
            g.SmoothingMode = baseScale < 1000 ? SmoothingMode.AntiAlias : SmoothingMode.HighSpeed;
            g.InterpolationMode = InterpolationMode.NearestNeighbor;
            g.PixelOffsetMode = PixelOffsetMode.None;

            var errorFont = new Font("Arial", 10.0f, FontStyle.Bold);

            if (Map == null)
            {
                g.DrawString("Map object not initialized", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (Palette == null)
            {
                g.DrawString("Palette object not initialized", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (Map.Nodes == null)
            {
                g.DrawString("Map has not started parsing", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (Map.Loading)
            {
                g.DrawString("Map has not completed parsing", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (!Map.Nodes.Any())
            {
                g.DrawString("Map has no data", errorFont, Palette.Error, 5, 5);
                return;
            }

            centerX = point.X;
            centerZ = point.Z;

            if (clip.Width > clip.Height)
            {
                totalX = baseScale;
                totalZ = (int)(baseScale * (float)clip.Height / clip.Width);
            }
            else
            {
                totalZ = baseScale;
                totalX = (int)(baseScale * (float)clip.Width / clip.Height);
            }

            var startX = clip.X + centerX - totalX;
            var endX = clip.X + centerX + totalX;
            var startZ = clip.Y + centerZ - totalZ;
            var endZ = clip.Y + centerZ + totalZ;

            var scaleX = clip.Width / (endX - startX);
            var scaleZ = clip.Height / (endZ - startZ);

            if (float.IsInfinity(scaleX) || float.IsNaN(scaleX))
                scaleX = clip.Width;
            if (float.IsInfinity(scaleZ) || float.IsNaN(scaleZ))
                scaleZ = clip.Height;

            var nodesNearby =
                Map.Nodes.Values.Where(
                    x => x.X >= startX - 1500 && x.X <= endX + 1500 && x.Z >= startZ - 1500 && x.Z <= endZ + 1500);
            var itemsNearby = nodesNearby.SelectMany(x => x.GetItems()).Where(x => x.HideUI == false).ToList();

            var prefabs = itemsNearby.Where(x => x.Type == Ets2ItemType.Prefab);

            var nodesToFollow = prefabs.SelectMany(x => x.NodesList.Values).Distinct();

            // Gather all prefabs, and issue a drawing command
            foreach (var node in nodesToFollow)
            {
                if (node == null)
                    continue;

                // Nodes from prefab are always like:
                // Prefab = Forward
                // Road=backward
                var road = node.ForwardItem != null && node.ForwardItem.Type == Ets2ItemType.Prefab
                    ? node.BackwardItem
                    : node.ForwardItem;
                var roadStart = road;
                var fw = node.ForwardItem != null && node.ForwardItem.Type == Ets2ItemType.Road;

                if (road == null)
                {
                    // DEAD END
                    continue;
                }

                var roadChain = new List<Ets2Item>();

                // Start drawing at start road
                if (fw)
                {
                    do
                    {
                        roadChain.Add(road);
                        road = road.EndNode == null ? null : road.EndNode.ForwardItem;
                    } while (road != null && road.Type == Ets2ItemType.Road);
                }
                else
                {
                    do
                    {
                        roadChain.Add(road);
                        road = road.StartNode == null ? null : road.StartNode.BackwardItem;
                    } while (road != null && road.Type == Ets2ItemType.Road);
                }

                if (!fw)
                    roadChain.Reverse();

                foreach (var n in roadChain.Where(x => x.HideUI == false))
                {
                    n.GenerateRoadPolygon(64);
                }

                // Generate drawing parameters
                var isHighway = roadStart != null && roadStart.RoadLook != null && roadStart.RoadLook.IsHighway;
                var isExpress = roadStart != null && roadStart.RoadLook != null && roadStart.RoadLook.IsExpress;
                var isLocal = roadStart != null && roadStart.RoadLook != null && roadStart.RoadLook.IsLocal;
                var roadWidth = (roadStart.RoadLook != null ? roadStart.RoadLook.GetTotalWidth() : 10.0f) * scaleX;
                var roadInGps = Route != null && !Route.Loading && Route.Roads != null && Route.Roads.Contains(roadStart);

                var pen = default(Pen);

                if (isHighway)
                {
                    pen = new Pen(roadInGps ? Palette.HighwayGPS : Palette.Highway, roadWidth);
                }
                else if (isExpress)
                {
                    pen = new Pen(roadInGps ? Palette.ExpressGPS : Palette.Express, roadWidth);
                }
                else if (isLocal)
                {
                    pen = new Pen(roadInGps ? Palette.LocalGPS : Palette.Local, roadWidth);
                }
                else
                {
                    pen = new Pen(Palette.Error, roadWidth);
                }


                var roadPoly =
                    roadChain.Where(x => x.HideUI == false)
                        .SelectMany(x => x.RoadPolygons)
                        .Select(x => new PointF((x.X - startX) * scaleX, (x.Z - startZ) * scaleZ));

                if (roadPoly.Any())
                {
                    g.DrawLines(pen, roadPoly.ToArray());
                }
            }

            // Cities?
            var cityFont = new Font("Arial", 10.0f);
            foreach (var cities in itemsNearby.Where(x => x.Type == Ets2ItemType.City && x.StartNode != null))
            {
                var ctX = cities.StartNode.X;
                var ctZ = cities.StartNode.Z;

                var mapX = (ctX - startX) * scaleX;
                var mapY = (ctZ - startZ) * scaleZ;
                //
                g.DrawString(cities.City, cityFont, Brushes.White, mapX, mapY);
            }

            // Draw all prefab curves
            foreach (var prefabItem in prefabs.Where(x => x.Prefab != null && x.HideUI == false).Distinct())
            {
                var inGps = Route != null && Route.Prefabs != null && Route.Prefabs.Any(x => x.Item1 == prefabItem);

                if (prefabItem.Prefab.Company != null)
                {
                    // TODO: Draw companies 
                }
                else
                {
                    var originNode = prefabItem.NodesList.FirstOrDefault().Value;
                    if (originNode != null)
                    {
                        foreach (
                            var poly in
                                prefabItem.Prefab.GeneratePolygonCurves(originNode, prefabItem.Origin))
                        {
                            var offsetPoly = poly.Select(x => new PointF((x.X - startX) * scaleX, (x.Z - startZ) * scaleZ)).ToArray();

                            var p = new Pen(inGps?Palette.PrefabGPS : Palette.Prefab, 1.0f);
                            g.DrawLines(p, offsetPoly);
                        }
                    }
                }
            }

            var rotation = point.Heading;

            var truckLength = 10;

            g.DrawLine(new Pen(Brushes.Cyan, 5.0f), scaleX * totalX + (float)Math.Sin(rotation) * truckLength * 2,
                scaleZ * totalZ + (float)Math.Cos(rotation) * truckLength * 2, scaleX * totalX, scaleZ * totalZ);
        }
예제 #22
0
        public void Render(Graphics g, Rectangle clip, float baseScale, Ets2Point point)
        {
            _clip = clip;

            g.FillRectangle(Palette.Background, new Rectangle(0, 0, clip.X + clip.Width, clip.Y + clip.Height));
            g.SmoothingMode     = baseScale < 1000 ? SmoothingMode.AntiAlias : SmoothingMode.HighSpeed;
            g.InterpolationMode = InterpolationMode.NearestNeighbor;
            g.PixelOffsetMode   = PixelOffsetMode.None;

            var errorFont = new Font("Arial", 10.0f, FontStyle.Bold);

            if (Map == null)
            {
                g.DrawString("Map object not initialized", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (Palette == null)
            {
                g.DrawString("Palette object not initialized", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (Map.Nodes == null)
            {
                g.DrawString("Map has not started parsing", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (Map.Loading)
            {
                g.DrawString("Map has not completed parsing", errorFont, Palette.Error, 5, 5);
                return;
            }
            if (!Map.Nodes.Any())
            {
                g.DrawString("Map has no data", errorFont, Palette.Error, 5, 5);
                return;
            }

            centerX = point.X;
            centerZ = point.Z;

            if (clip.Width > clip.Height)
            {
                totalX = baseScale;
                totalZ = (int)(baseScale * (float)clip.Height / clip.Width);
            }
            else
            {
                totalZ = baseScale;
                totalX = (int)(baseScale * (float)clip.Width / clip.Height);
            }

            var startX = clip.X + centerX - totalX;
            var endX   = clip.X + centerX + totalX;
            var startZ = clip.Y + centerZ - totalZ;
            var endZ   = clip.Y + centerZ + totalZ;

            var scaleX = clip.Width / (endX - startX);
            var scaleZ = clip.Height / (endZ - startZ);

            if (float.IsInfinity(scaleX) || float.IsNaN(scaleX))
            {
                scaleX = clip.Width;
            }
            if (float.IsInfinity(scaleZ) || float.IsNaN(scaleZ))
            {
                scaleZ = clip.Height;
            }

            var nodesNearby =
                Map.Nodes.Values.Where(
                    x => x.X >= startX - 1500 && x.X <= endX + 1500 && x.Z >= startZ - 1500 && x.Z <= endZ + 1500);
            var itemsNearby = nodesNearby.SelectMany(x => x.GetItems()).Where(x => x.HideUI == false).ToList();

            var prefabs = itemsNearby.Where(x => x.Type == Ets2ItemType.Prefab);

            var nodesToFollow = prefabs.SelectMany(x => x.NodesList.Values).Distinct();

            // Gather all prefabs, and issue a drawing command
            foreach (var node in nodesToFollow)
            {
                if (node == null)
                {
                    continue;
                }

                // Nodes from prefab are always like:
                // Prefab = Forward
                // Road=backward
                var road      = node.ForwardItem?.Type == Ets2ItemType.Prefab ? node.BackwardItem : node.ForwardItem;
                var roadStart = road;
                var fw        = node.ForwardItem?.Type == Ets2ItemType.Road;

                if (road == null)
                {
                    // DEAD END
                    continue;
                }

                var roadChain = new List <Ets2Item>();

                // Start drawing at start road
                if (fw)
                {
                    do
                    {
                        roadChain.Add(road);
                        road = road.EndNode?.ForwardItem;
                    } while (road != null && road.Type == Ets2ItemType.Road);
                }
                else
                {
                    do
                    {
                        roadChain.Add(road);
                        road = road.StartNode?.BackwardItem;
                    } while (road != null && road.Type == Ets2ItemType.Road);
                }

                if (!fw)
                {
                    roadChain.Reverse();
                }

                foreach (var n in roadChain.Where(x => x.HideUI == false))
                {
                    n.GenerateRoadPolygon(64);
                }

                // Generate drawing parameters
                var isHighway    = roadStart?.RoadLook?.IsHighway == true;
                var isExpress    = roadStart?.RoadLook?.IsExpress == true;
                var isLocal      = roadStart?.RoadLook?.IsLocal == true;
                var isNoVehicles = roadStart?.RoadLook?.IsNoVehicles == true;
                var roadWidth    = (roadStart?.RoadLook?.GetTotalWidth() ?? 10.0f) * scaleX;
                var roadInGps    = Route != null && !Route.Loading && Route.Roads != null && Route.Roads.Contains(roadStart);

                var pen = default(Pen);

                if (isHighway)
                {
                    pen = new Pen(roadInGps ? Palette.HighwayGPS : Palette.Highway, roadWidth);
                }
                else if (isExpress)
                {
                    pen = new Pen(roadInGps ? Palette.ExpressGPS : Palette.Express, roadWidth);
                }
                else if (isLocal)
                {
                    pen = new Pen(roadInGps ? Palette.LocalGPS : Palette.Local, roadWidth);
                }
                else if (isNoVehicles)
                {
                    pen = new Pen(Palette.NoVehicles, roadWidth);
                }
                else
                {
                    pen = new Pen(Palette.Error, roadWidth);
                }


                var roadPoly =
                    roadChain.Where(x => x.HideUI == false)
                    .SelectMany(x => x.RoadPolygons)
                    .Select(x => new PointF((x.X - startX) * scaleX, (x.Z - startZ) * scaleZ));

                if (roadPoly.Any())
                {
                    g.DrawLines(pen, roadPoly.ToArray());
                }
            }

            // Cities?
            var cityFont = new Font("Arial", 10.0f);

            foreach (var cities in itemsNearby.Where(x => x.Type == Ets2ItemType.City && x.StartNode != null && !x.HideUI))
            {
                var ctX = cities.StartNode.X;
                var ctZ = cities.StartNode.Z;

                var mapX = (ctX - startX) * scaleX;
                var mapY = (ctZ - startZ) * scaleZ;
                //
                g.DrawString(cities.City, cityFont, Brushes.White, mapX, mapY);
            }

            // Draw all prefab curves
            foreach (var prefabItem in prefabs.Where(x => x.Prefab != null && x.HideUI == false).Distinct())
            {
                var inGps = Route != null && Route.Prefabs != null && Route.Prefabs.Any(x => x.Item1 == prefabItem);

                if (prefabItem.Prefab.Company != null)
                {
                    // TODO: Draw companies
                }
                else
                {
                    var originNode = prefabItem.NodesList.FirstOrDefault().Value;
                    if (originNode != null)
                    {
                        foreach (
                            var poly in
                            prefabItem.Prefab.GeneratePolygonCurves(originNode, prefabItem.Origin))
                        {
                            var offsetPoly = poly.Select(x => new PointF((x.X - startX) * scaleX, (x.Z - startZ) * scaleZ)).ToArray();

                            var p = new Pen(inGps?Palette.PrefabGPS : Palette.Prefab, 1.0f);
                            g.DrawLines(p, offsetPoly);
                        }
                    }
                }
            }

            var rotation = point.Heading;

            var truckLength = 10;

            g.DrawLine(new Pen(Brushes.Cyan, 5.0f), scaleX * totalX + (float)Math.Sin(rotation) * truckLength * 2,
                       scaleZ * totalZ + (float)Math.Cos(rotation) * truckLength * 2, scaleX * totalX, scaleZ * totalZ);
        }