Esempio n. 1
0
        public void Gradient()
        {
            var f = new PiecewiseLinearFunction <double>(new List <IVector <double> >()
            {
                new Vector <double>(1d), new Vector <double>(2d)
            });

            var grad = f.Gradient(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                                  new Vector <double>(0.5d));

            Assert.True(grad.Count == 6);
            Assert.True(grad.Skip(2).All(x => Math.Abs(x) < 1e-14));
            Assert.True(Math.Abs(grad[0] - 0.5) < 1e-14);
            Assert.True(Math.Abs(grad[1] - 1) < 1e-14);

            grad = f.Gradient(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                              new Vector <double>(1.5d));

            Assert.True(grad.Count == 6);
            Assert.True(grad.Take(2).All(x => Math.Abs(x) < 1e-14));
            Assert.True(grad.TakeLast(2).All(x => Math.Abs(x) < 1e-14));
            Assert.True(Math.Abs(grad[2] - 1.5) < 1e-14);
            Assert.True(Math.Abs(grad[3] - 1) < 1e-14);

            grad = f.Gradient(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                              new Vector <double>(3d));

            Assert.True(grad.Count == 6);
            Assert.True(grad.Take(4).All(x => Math.Abs(x) < 1e-14));
            Assert.True(Math.Abs(grad[4] - 3) < 1e-14);
            Assert.True(Math.Abs(grad[5] - 1) < 1e-14);

            grad = f.Gradient(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                              new Vector <double>(2d));

            Assert.True(grad.Count == 6);
            Assert.True(grad.Count == 6);
            Assert.True(grad.Take(4).All(x => Math.Abs(x) < 1e-14));
            Assert.True(Math.Abs(grad[4] - 2) < 1e-14);
            Assert.True(Math.Abs(grad[5] - 1) < 1e-14);

            Assert.True(1e-14 > 6 - f.Value(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                                            new Vector <double>(new[] { 1d })));

            grad = f.Gradient(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                              new Vector <double>(1.5d));

            Assert.True(grad.Count == 6);
            Assert.True(grad.Take(2).All(x => Math.Abs(x) < 1e-14));
            Assert.True(grad.TakeLast(2).All(x => Math.Abs(x) < 1e-14));
            Assert.True(Math.Abs(grad[2] - 1.5) < 1e-14);
            Assert.True(Math.Abs(grad[3] - 1) < 1e-14);
        }
 public static BTStatus LandMovement(Animal agent, Vector2 direction, float speed, AnimalAnimationState state, float minDistance = 2f, float maxDistance = 20f, float minDirectionOffsetDegrees = 0, float maxDirectionOffsetDegrees = 360, int tryCount = 10)
 {
     var search = AIUtilities.FindRoute(agent.Position, 2f, 20f, direction);
     if (search != null)
     {
         var smoothed = search.LineOfSightSmooth(agent.Position);
         PiecewiseLinearFunction route = AIUtilities.ProjectRoute(smoothed, speed);
         agent.NextTick = WorldTime.Seconds + route.EndTime;
         agent.Target.SetPath(route);
         agent.AnimationState = state;
         return BTStatus.Success;
     }
     else
         return LandAnimalUnStuckOrDie(agent, speed, state);
 }
Esempio n. 3
0
        internal void GetMembership_WithVariousInputs_ReturnsExpectedResult(double x, double expected)
        {
            // Arrange
            var points = new FuzzyPoint[]
            {
                new FuzzyPoint(2, 0.5),
                new FuzzyPoint(3, 1)
            };

            var function = new PiecewiseLinearFunction(points);

            // Act
            var result = function.GetMembership(x);

            // Assert
            Assert.Equal(UnitInterval.Create(expected), result);
        }
        public static BTStatus AmphibiousMovement(Animal agent, Vector2 generalDirection, float speed, AnimalAnimationState state, float minDistance = 2f, float maxDistance = 20f)
        {
            var start = agent.Position.WorldPosition3i;
            if (!World.World.IsUnderwater(start))
                start = RouteManager.NearestWalkableY(agent.Position.WorldPosition3i);

            if (!start.IsValid)
                return LandMovement(agent, generalDirection, speed, state, minDistance, maxDistance);

            if (generalDirection == Vector2.zero)
                generalDirection = Vector2.right.Rotate(RandomUtil.Range(0f, 360));
            else
                generalDirection = generalDirection.Normalized;

            var target = (agent.Position + (generalDirection * RandomUtil.Range(minDistance, maxDistance)).X_Z()).WorldPosition3i;
            if (World.World.IsUnderwater(target))
                target.y = World.World.MaxWaterHeight[target];
            else
                target = RouteManager.NearestWalkableXYZ(target, 5);

            // This is a low-effort search that includes water surface and should occasionally fail, just pick a semi-random node that was visited when it fails
            var allowWaterSearch = new AStarSearch(RouteCacheData.NeighborsIncludeWater, start, target, 30);
            if (allowWaterSearch.Status != SearchStatus.PathFound)
            {
                target = allowWaterSearch.Nodes.Last().Key;
                allowWaterSearch.GetPath(target);
            }

            if (allowWaterSearch.Path.Count < 2)
                return BTStatus.Failure;
            else if (allowWaterSearch.Status == SearchStatus.Unpathable && allowWaterSearch.Nodes.Count < RouteRegions.MinimumRegionSize && !World.World.IsUnderwater(agent.Position.WorldPosition3i))
            {
                // Search region was unexpectedly small and agent is on land, might be trapped by player construction. 
                // Try regular land movement so region checks can apply & the agent can get unstuck (or die)
                return LandMovement(agent, generalDirection, speed, state, minDistance, maxDistance);
            }

            var smoothed = allowWaterSearch.LineOfSightSmooth(agent.Position);
            PiecewiseLinearFunction route = AIUtilities.ProjectRoute(smoothed, speed);
            agent.AnimationState = state;
            agent.NextTick = WorldTime.Seconds + route.EndTime;
            agent.Target.SetPath(route);

            return BTStatus.Success;
        }
Esempio n. 5
0
        internal void LowerBound_ReturnsExpectedResult()
        {
            // Arrange
            // Arrange
            var points = new FuzzyPoint[]
            {
                new FuzzyPoint(2, 0.5),
                new FuzzyPoint(3, 1)
            };

            var function = new PiecewiseLinearFunction(points);

            // Act
            var result = function.LowerBound;

            // Assert
            Assert.Equal(2, result);
        }
Esempio n. 6
0
        internal void MaxY_ReturnsExpectedResult()
        {
            // Arrange
            // Arrange
            var points = new FuzzyPoint[]
            {
                new FuzzyPoint(2, 0),
                new FuzzyPoint(3, 1)
            };

            var function = new PiecewiseLinearFunction(points);

            // Act
            var result = function.MaxY;

            // Assert
            Assert.Equal(UnitInterval.One(), result);
        }
Esempio n. 7
0
        public void Value()
        {
            var f = new PiecewiseLinearFunction <double>(new List <IVector <double> >()
            {
                new Vector <double>(1d), new Vector <double>(2d)
            });

            Assert.True(1e-14 > Math.Abs(0 - f.Value(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                                                     new Vector <double>(0.5d))));

            Assert.True(1e-14 > Math.Abs(7.5 - f.Value(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                                                       new Vector <double>(1.5d))));

            Assert.True(1e-14 > Math.Abs(40 - f.Value(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                                                      new Vector <double>(3d))));

            Assert.True(1e-14 > Math.Abs(30 - f.Value(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                                                      new Vector <double>(new[] { 2d }))));

            Assert.True(1e-14 > Math.Abs(6 - f.Value(new Vector <double>(new[] { 0d, 0d, 3d, 3d, 10d, 10d }),
                                                     new Vector <double>(new[] { 1d }))));
        }
Esempio n. 8
0
    public ContourAnimationInfo getContourAnimations(ContourQuery contourQuery)
    {
        List <List <TrendingDataLocation> > frames     = GetFramesFromHistorian(contourQuery);
        PiecewiseLinearFunction             colorScale = GetColorScale(contourQuery);
        Func <double, double> colorFunc = colorScale;

        // The actual startDate is the timestamp of the
        // first frame after contourQuery.GetStartDate()
        DateTime startDate       = contourQuery.GetStartDate();
        int      stepSize        = contourQuery.StepSize;
        int      startTimeOffset = (int)Math.Ceiling((startDate - startDate.Date).TotalMinutes / stepSize);

        startDate = startDate.Date.AddMinutes(startTimeOffset * stepSize);
        double latDif = frames.Min(frame => frame.Max(location => location.Latitude)) - frames.Min(frame => frame.Min(location => location.Latitude));
        double lonDif = frames.Min(frame => frame.Max(location => location.Longitude)) - frames.Min(frame => frame.Min(location => location.Longitude));

        double minLat = frames.Min(frame => frame.Min(location => location.Latitude)) - (latDif * 0.1D);
        double maxLat = frames.Min(frame => frame.Max(location => location.Latitude)) + (latDif * 0.1D);
        double minLng = frames.Min(frame => frame.Min(location => location.Longitude)) - (lonDif * 0.1D);
        double maxLng = frames.Min(frame => frame.Max(location => location.Longitude)) + (lonDif * 0.1D);

        GeoCoordinate topLeft     = new GeoCoordinate(maxLat, minLng);
        GeoCoordinate bottomRight = new GeoCoordinate(minLat, maxLng);

        GSF.Drawing.Point topLeftPoint     = s_crs.Translate(topLeft, contourQuery.Resolution);
        GSF.Drawing.Point bottomRightPoint = s_crs.Translate(bottomRight, contourQuery.Resolution);

        topLeftPoint     = new GSF.Drawing.Point(Math.Floor(topLeftPoint.X), Math.Floor(topLeftPoint.Y));
        bottomRightPoint = new GSF.Drawing.Point(Math.Ceiling(bottomRightPoint.X), Math.Ceiling(bottomRightPoint.Y));
        topLeft          = s_crs.Translate(topLeftPoint, contourQuery.Resolution);
        bottomRight      = s_crs.Translate(bottomRightPoint, contourQuery.Resolution);

        int width  = (int)(bottomRightPoint.X - topLeftPoint.X + 1);
        int height = (int)(bottomRightPoint.Y - topLeftPoint.Y + 1);

        int    animationID;
        string timeZoneID = null;

        using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
        {
            connection.ExecuteNonQuery("INSERT INTO ContourAnimation(ColorScaleName, StartTime, EndTime, StepSize) VALUES({0}, {1}, {2}, {3})", contourQuery.ColorScaleName, contourQuery.GetStartDate(), contourQuery.GetEndDate(), contourQuery.StepSize);
            animationID = connection.ExecuteScalar <int>("SELECT @@IDENTITY");

            if (contourQuery.IncludeWeather)
            {
                timeZoneID = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'XDATimeZone'");
            }
        }

        GSF.Threading.CancellationToken cancellationToken = new GSF.Threading.CancellationToken();
        s_cancellationTokens[animationID] = cancellationToken;

        ProgressCounter progressCounter = new ProgressCounter(frames.Count);

        s_progressCounters[animationID] = progressCounter;

        Action <int> createFrame = i =>
        {
            List <TrendingDataLocation> frame = frames[i];
            IDWFunc idwFunction = GetIDWFunction(contourQuery, frame);
            uint[]  pixelData;

            if (contourQuery.IncludeWeather)
            {
                TimeZoneInfo tzInfo = !string.IsNullOrEmpty(timeZoneID)
                    ? TimeZoneInfo.FindSystemTimeZoneById(timeZoneID)
                    : TimeZoneInfo.Local;

                // Weather data is only available in 5-minute increments
                DateTime frameTime      = TimeZoneInfo.ConvertTimeToUtc(startDate.AddMinutes(stepSize * i), tzInfo);
                double   minutes        = (frameTime - frameTime.Date).TotalMinutes;
                int      weatherMinutes = (int)Math.Ceiling(minutes / 5) * 5;

                NameValueCollection queryString = HttpUtility.ParseQueryString(string.Empty);
                queryString["service"]     = "WMS";
                queryString["request"]     = "GetMap";
                queryString["layers"]      = "nexrad-n0r-wmst";
                queryString["format"]      = "image/png";
                queryString["transparent"] = "true";
                queryString["version"]     = "1.1.1";
                queryString["time"]        = frameTime.Date.AddMinutes(weatherMinutes).ToString("o");
                queryString["height"]      = height.ToString();
                queryString["width"]       = width.ToString();
                queryString["srs"]         = "EPSG:3857";

                GSF.Drawing.Point topLeftProjected     = s_crs.Projection.Project(topLeft);
                GSF.Drawing.Point bottomRightProjected = s_crs.Projection.Project(bottomRight);
                queryString["bbox"] = string.Join(",", topLeftProjected.X, bottomRightProjected.Y, bottomRightProjected.X, topLeftProjected.Y);

                string weatherURL = "http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi?" + queryString.ToString();

                using (WebClient client = new WebClient())
                    using (MemoryStream stream = new MemoryStream(client.DownloadData(weatherURL)))
                        using (Bitmap bitmap = new Bitmap(stream))
                        {
                            pixelData = bitmap.ToPixelData();
                        }
            }
            else
            {
                pixelData = new uint[width * height];
            }

            if (cancellationToken.IsCancelled)
            {
                return;
            }

            for (int x = 0; x < width; x++)
            {
                if (cancellationToken.IsCancelled)
                {
                    return;
                }

                for (int y = 0; y < height; y++)
                {
                    if (cancellationToken.IsCancelled)
                    {
                        return;
                    }

                    if (pixelData[y * width + x] > 0)
                    {
                        continue;
                    }

                    GSF.Drawing.Point offsetPixel       = new GSF.Drawing.Point(topLeftPoint.X + x, topLeftPoint.Y + y);
                    GeoCoordinate     pixelCoordinate   = s_crs.Translate(offsetPixel, contourQuery.Resolution);
                    double            interpolatedValue = idwFunction(pixelCoordinate.Longitude, pixelCoordinate.Latitude);
                    pixelData[y * width + x] = (uint)colorFunc(interpolatedValue);
                }
            }

            if (cancellationToken.IsCancelled)
            {
                return;
            }

            using (Bitmap bitmap = BitmapExtensions.FromPixelData(width, pixelData))
                using (MemoryStream stream = new MemoryStream())
                {
                    bitmap.Save(stream, ImageFormat.Png);

                    using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
                    {
                        connection.ExecuteNonQuery("INSERT INTO ContourAnimationFrame VALUES({0}, {1}, {2})", animationID, i, stream.ToArray());
                    }
                }

            progressCounter.Increment();
        };

        Task.Run(() =>
        {
            ICancellationToken token;
            ProgressCounter counter;
            Parallel.For(0, frames.Count, createFrame);
            s_cancellationTokens.TryRemove(animationID, out token);
            s_progressCounters.TryRemove(animationID, out counter);

            if (cancellationToken.IsCancelled)
            {
                using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
                {
                    connection.ExecuteNonQuery("DELETE FROM ContourAnimationFrame WHERE ContourAnimationID = {0}", animationID);
                    connection.ExecuteNonQuery("DELETE FROM ContourAnimation WHERE ID = {0}", animationID);
                }
            }
        });

        s_cleanUpAnimationOperation.TryRunOnceAsync();

        return(new ContourAnimationInfo()
        {
            AnimationID = animationID,
            ColorDomain = colorScale.Domain,
            ColorRange = colorScale.Range,
            MinLatitude = bottomRight.Latitude,
            MaxLatitude = topLeft.Latitude,
            MinLongitude = topLeft.Longitude,
            MaxLongitude = bottomRight.Longitude,
            Infos = frames.Select((frame, index) => new ContourInfo()
            {
                Locations = frame,
                URL = string.Format("./mapService.asmx/getContourAnimationFrame?animation={0}&frame={1}", animationID, index),
                Date = contourQuery.GetStartDate().AddMinutes(index * contourQuery.StepSize).ToString()
            }).ToList()
        });
    }
        public static IEnumerator <BTStatus> FoodFinder(Animal agent, Func <Animal, BTStatus> noNearbyFoodBehavior, float hungerRestored)
        {
            var             lastPos     = Vector3.Zero;
            Queue <Vector3> foodSources = new Queue <Vector3>();

            while (agent.Hunger > Brain.HungerSatiated)
            {
                foodSources.Clear();
                while (foodSources.Count == 0)
                {
                    if (Vector3.WrappedDistanceSq(lastPos, agent.Position) > 100)
                    {
                        var agentRegion = RouteRegions.GetRegion(agent.Position.WorldPosition3i);
                        foodSources.AddRange(EcoSim.PlantSim.PlantsWithinRange(agent.Position, 10, plant => agent.Species.Eats(plant.Species) &&
                                                                               RouteRegions.GetRegion(plant.Position.WorldPosition3i.Down()) == agentRegion).Shuffle().Select(plant => plant.Position + Vector3.Down));
                        lastPos = agent.Position;
                    }
                    else
                    {
                        yield return(noNearbyFoodBehavior(agent));
                    }
                }

                while (foodSources.Count > 0 && agent.Hunger > Brain.HungerSatiated && Vector3.WrappedDistanceSq(lastPos, agent.Position) < 100)
                {
                    // low-effort search for the first option or any other option visited while trying to hit the first
                    Vector3 targetPlantPosition;
                    PiecewiseLinearFunction route = AIUtilities.GetRouteToAny(agent.Position, foodSources, agent.Species.WanderingSpeed, out targetPlantPosition, 100, 20, agent.Species.HeadDistance);
                    if (route == null)
                    {
                        break;
                    }
                    agent.Target.SetPath(route);
                    agent.Target.LookPos = targetPlantPosition;
                    agent.AnimationState = AnimalAnimationState.LookingForFood;
                    var target = route.EndPosition;

                    // just in case something interrupts the path
                    while (agent.Target.TargetTime > WorldTime.Seconds && agent.Target.TargetPosition == target)
                    {
                        agent.NextTick = agent.Target.TargetTime;
                        yield return(BTStatus.Running);
                    }

                    if (Vector3.WrappedDistanceSq(target, agent.Position) < 4)
                    {
                        agent.AnimationState = AnimalAnimationState.Eating;
                        agent.NextTick       = WorldTime.Seconds + 10;
                        agent.Hunger        -= hungerRestored;
                        agent.Target.LookPos = targetPlantPosition;
                        yield return(BTStatus.Running);
                    }

                    // something interrupted eating, probably need to find new food
                    if (agent.Target.TargetPosition != target)
                    {
                        break;
                    }
                }
            }
        }