public void PerimeterBounceStatistics()
        {
            var jaxOpsArea = new GeoArray(
                new Geo(29.3590, -79.2195),
                new Geo(31.1627, -79.2195),
                new Geo(31.1627, -81.2789),
                new Geo(30.1627, -81.2789),
                new Geo(29.3590, -80.8789),
                new Geo(29.3590, -79.2195));

            var failures = 0;
            var successes = 0;
            while (failures < 100)
            {
                GeoArray result = null;
                while (result == null)
                {
                    try
                    {
                        result = jaxOpsArea.PerimeterBounce(null, double.NaN, 1e6);
                        successes++;
                        if (successes % 10000 == 0) Debug.WriteLine("Test in progress.  Successes: {0}  Failures: {1}  Success/Fail Ratio: {2:0.00%}", successes, failures, (float)successes / (float)(successes + failures));

                    }
                    catch (PerimeterBounceException ex)
                    {
                        Debug.WriteLine(ex.Message);
                        failures++;
                        Debug.WriteLine("Test in progress.  Successes: {0}  Failures: {1}  Success/Fail Ratio: {2:0.00%}", successes, failures, (float)successes / (float)(successes + failures));
                    }
                }
            }
            Debug.WriteLine("Test complete.  Successes: {0}  Failures: {1}  Success/Fail Ratio: {2:0.00%}", successes, failures, (float)successes / (float)(successes + failures));
        }
        public static Animat Seed(ScenarioSpecies species, GeoRect geoRect, Bathymetry bathymetry)
        {
            var bounds = new GeoArray(geoRect.NorthWest, geoRect.NorthEast, geoRect.SouthEast, geoRect.SouthWest, geoRect.NorthWest);
            var result = new Animat { ScenarioSpecies = species };

            var area = bounds.Area;
            //Debug.WriteLine("Area: {0}",area);
            var population = (int)Math.Floor(area * species.PopulationDensity);
            for (var i = 0; i < population; i++)
            {
                var location = bounds.RandomLocationWithinPerimeter();
                var depth = bathymetry.Samples.GetNearestPoint(location).Data;
                if (depth < 0) result.Locations.Add(new Geo<float>(location.Latitude, location.Longitude, (float)(depth * Random.NextDouble())));
            }
            result.TotalAnimats = population;
            return result;
        }
        /// <summary>
        /// Adapted from http://msdn.microsoft.com/en-us/library/cc451895.aspx
        /// </summary>
        /// <param name="geo"></param>
        /// <param name="region"></param>
        /// <returns></returns>
        public static bool IsInside(this Geo geo, GeoArray region)
        {
            if (region == null) throw new ArgumentNullException("region");
            if (!region.IsClosed) throw new ArgumentException("Region must be closed", "region");
            var points = region.ToArray();

            var j = points.Length - 1;
            var inPoly = false;

            for (var i = 0; i < points.Length; i++)
            {
                if (points[i].Longitude < geo.Longitude && points[j].Longitude >= geo.Longitude || 
                    points[j].Longitude < geo.Longitude && points[i].Longitude >= geo.Longitude) 
                    if (points[i].Latitude + (geo.Longitude - points[i].Longitude) / (points[j].Longitude - points[i].Longitude) * 
                        (points[j].Latitude - points[i].Latitude) < geo.Latitude) 
                        inPoly = !inPoly;
                j = i;
            }
            return inPoly;
        }
 public async static Task<Animat> SeedAsyncWithout3MB(ScenarioSpecies species, GeoRect geoRect, Bathymetry bathymetry)
 {
     var bounds = new GeoArray(geoRect.NorthWest, geoRect.NorthEast, geoRect.SouthEast, geoRect.SouthWest, geoRect.NorthWest);
     var result = new Animat { ScenarioSpecies = species };
     
     var area = bounds.Area;
     //Debug.WriteLine("Area: {0}",area);
     var transformManyBlock = new TransformManyBlock<int, Geo<float>>(count =>
     {
         var geos = new List<Geo<float>>();
         for (var i = 0; i < count; i++)
         {
             var location = bounds.RandomLocationWithinPerimeter();
             var depth = bathymetry.Samples.GetNearestPointAsync(location).Result.Data;
             if (depth < -50) geos.Add(new Geo<float>(location.Latitude, location.Longitude, (float)(depth * Random.NextDouble())));
         }
         return geos;
     }, new ExecutionDataflowBlockOptions
     {
         TaskScheduler = TaskScheduler.Default,
         BoundedCapacity = -1,
         MaxDegreeOfParallelism = -1,
     });
     var bufferBlock = new BufferBlock<Geo<float>>();
     transformManyBlock.LinkTo(bufferBlock);
     var population = (int)Math.Round(area * species.PopulationDensity);
     result.TotalAnimats = population;
     const int blockSize = 100;
     while (population > 0)
     {
         transformManyBlock.Post(population > blockSize ? blockSize : population);
         population -= blockSize;
     }
     transformManyBlock.Complete();
     await transformManyBlock.Completion;
     IList<Geo<float>> animatGeos;
     if (bufferBlock.TryReceiveAll(out animatGeos))
         result.Locations.AddRange(animatGeos);
     return result;
 }
        /// <summary>
        /// Is geo inside region?
        /// Region must be closed.
        /// It is recommended that a bounds check is run before this method is called. 
        /// This method will return true if either geo or it's antipode are inside the region
        /// </summary>
        /// <param name="geo"></param>
        /// <param name="region"></param>
        /// <returns></returns>
        public static bool IsInsideBAD(this Geo geo, GeoArray region)
        {
            if (region == null) throw new ArgumentNullException("region");
            if (!region.IsClosed) throw new ArgumentException("Region must be closed", "region");

            var c = region.Center;

            // bail out if the point is more than 90 degrees off the centroid
            if (geo.DistanceRadians(c) >= MoreMath.PiOverTwo) throw new ArgumentException("Point cannot be more than 90 degrees from center of region to test", "geo");
            
            // ray is normal to the great circle from c to x.
            var ray = c.CrossNormalize(geo);

            // side is a point on the great circle between c and x. It is used to choose a direction.
            var side = geo.CrossNormalize(ray);
            var isIn = false;
            foreach (var segment in region.Segments)
            {
                if ((segment[0].Dot(ray) < 0.0) != (segment[1].Dot(ray) < 0.0) && segment.GreatCircleIntersection(ray).Dot(side) > 0.0)
                    isIn = !isIn;
            }
            return isIn;
        }
        public static bool IsInsideOld(this Geo geo, GeoArray region)
        {
            if (region == null) throw new ArgumentNullException("region");
            if (!region.BoundingBox.Contains(geo)) return false;

            if (!region.IsClosed) throw new ArgumentException("Region must be closed", "region");

            var c = region.Center;
            // bail out if the point is more than 90 degrees off the centroid
            if (geo.DistanceRadians(c) >= MoreMath.PiOverTwo) throw new ArgumentException("Point cannot be more than 90 degrees from center of region to test", "geo");

            var n = region.Length - 1;
            var v = region.ToArray();

            var wn = 0;    // the winding number counter

            // loop through all edges of the polygon
            for (var i = 0; i < n; i++)
            {   // edge from V[i] to V[i+1]
                if (v[i].Latitude <= geo.Latitude)
                {
                    // start y <= P.y
                    if ((v[i + 1].Latitude > geo.Latitude) &&   // an upward crossing and
                        (IsLeft(v[i], v[i + 1], geo) > 0))      // P left of edge
                        ++wn;                                   // have a valid up intersect
                }
                else
                {
                    // start y > P.y (no test needed)
                    if ((v[i + 1].Latitude <= geo.Latitude) &&  // a downward crossing
                        (IsLeft(v[i], v[i + 1], geo) < 0))      // P right of edge
                        --wn;                                   // have a valid down intersect
                }
            }
            return wn != 0;
        }
        /**
    * this can be used to set up the "rest" of the Limit if created from
    * serialization. just make it public
    */

        void Initialize()
        {
            foreach (var geo in Geos)
            {
                // this reason we extract a rectangular extents is
                // for placing random points within the area.
                if (geo.Latitude < _minLat) _minLat = geo.Latitude;
                if (geo.Latitude > _maxLat) _maxLat = geo.Latitude;
                if (geo.Longitude < _minLon) _minLon = geo.Longitude;
                if (geo.Longitude > _maxLon) _maxLon = geo.Longitude;
            }
            // need this for a few things

            // create a region for testing inside / outside
            _region = new GeoArray(Geos);

            // BoundingCircle attempt to get the center of the polygon. when the
            // shape is not a poly, it hacks a fur ball
            _boundingCircle = Geos.Count < 3 ? new BoundingCircle(new Geo(0.0, 0.0), 0.0) : new BoundingCircle(_region);

            _centerOfRegion = _boundingCircle.Center;

            SetIsClockWise();
        }
 /// <summary>
 /// Does the point s come within 'near' radians of the border of the region defined by the polygon in array?
 /// </summary>
 /// <param name="s"></param>
 /// <param name="array"></param>
 /// <param name="near"></param>
 /// <returns></returns>
 public static bool IsNear(this Geo s, GeoArray array, double near)
 {
     return array.Segments.Any(segment => s.IsNear(segment, near));
 }
Beispiel #9
0
 public void Setup()
 {
     array = new GeoArray();
 }
        public void PlatformBehaviorToKML()
        {
            var jaxOpsArea = new GeoArray(new Geo(29.3590, -79.2195),
                                          new Geo(31.1627, -79.2195),
                                          new Geo(31.1627, -81.2789),
                                          new Geo(30.1627, -81.2789),
                                          new Geo(29.3590, -80.8789),
                                          new Geo(29.3590, -79.2195));

            var platform = new Platform
            {
                PlatformName = "Test Platform",
                Perimeter = jaxOpsArea,
                Depth = 0,
                IsRandom = true,
                TrackType = TrackType.PerimeterBounce,
                Sources = new ObservableList<Source>(),
                Speed = 20,
            };
            var source = new Source
            {
                SourceName = "Test Source",
                Modes = new ObservableList<Mode>(),
                Platform = platform,
            };
            platform.Sources.Add(source);
            var mode = new Mode
            {
                ModeName = "Test Mode",
                PulseInterval = new TimeSpan(0, 0, 0, 10),
                PulseLength = new TimeSpan(0, 0, 0, 0, 500),
                Depth = 5,
                HighFrequency = 1000,
                LowFrequency = 1000,
                DepressionElevationAngle = 10,
                VerticalBeamWidth = 90,
                SourceLevel = 200,
                Source = source,
            };
            source.Modes.Add(mode);

            var behavior = new PlatformBehavior(platform, new TimeSpan(0, 0, 0, 1), 86400);
#if true
            var kml = new KMLRoot();
            var folder = new Folder("Jacksonville");
            jaxOpsArea.Placemark.name = "Jacksonville OpArea";
            jaxOpsArea.Placemark.Snippet = "The operational area";
            jaxOpsArea.Placemark.Snippet.maxLines = 1;
            folder.Add(jaxOpsArea.Placemark);

#if true
            var timeStep = 0;
            foreach (var state in behavior.PlatformStates)
            {
                if (timeStep % 100 == 0)
                {
                    state.PlatformLocation.Location.Placemark.name = string.Format("TimeStep {0}", timeStep);
                    folder.Add(state.PlatformLocation.Location.Placemark);
                }
                timeStep++;
            }
#else
            result.Placemark.name = "Platform track";
            result.Placemark.Snippet = "The track of the platform";
            result.Placemark.Snippet.maxLines = 1;
            result.Placemark.Geometry.AltitudeMode = AltitudeMode.clampedToGround;
            folder.Add(result.Placemark);
#endif

            kml.Document.Add(folder);

            var savePath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "Platform Behavior Tests", "PlatformBehavior.kml");
            Debug.WriteLine("Saving KML...");
            kml.Save(savePath);
#endif
        }
        public async static Task<Animat> SeedAsync(ScenarioSpecies species, GeoRect geoRect, Bathymetry bathymetry)
        {
            var yxzFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".txt");
            bathymetry.ToYXZ(yxzFileName, -1);
            var mbs = new C3mbs();
            mbsRESULT mbsResult;
            if (mbsRESULT.OK != (mbsResult = mbs.SetOutputDirectory(Path.GetTempPath())))
                throw new AnimatInterfaceMMBSException("SetOutputDirectory Error:" + mbs.ResultToTc(mbsResult));
            var config = mbs.GetConfiguration();
            config.enabled = false;             // binary output enabled/disabled
            config.durationLess = true;         // make sure we're in durationless mode.
            mbs.SetConfiguration(config);
            mbsResult = mbs.LoadBathymetryFromTextFile(yxzFileName);
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException("Bathymetry failed to load: " + mbs.ResultToTc(mbsResult));
            mbsResult = mbs.AddSpecies(species.SpeciesDefinitionFilePath);
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException(string.Format("C3mbs::AddSpecies FATAL error {0} for species {1}", mbs.ResultToTc(mbsResult), species.SpeciesDefinitionFilePath));

            var bounds = new GeoArray(geoRect.NorthWest, geoRect.NorthEast, geoRect.SouthEast, geoRect.SouthWest, geoRect.NorthWest);
            var result = new Animat { ScenarioSpecies = species };
            
            var area = bounds.Area;
            //Debug.WriteLine("Area: {0}",area);
            var transformManyBlock = new TransformManyBlock<int, Geo<float>>(count =>
            {
                var geos = new List<Geo<float>>();
                for (var i = 0; i < count; i++)
                {
                    var location = bounds.RandomLocationWithinPerimeter();
                    var depth = bathymetry.Samples.GetNearestPointAsync(location).Result.Data;
                    mbsRESULT retval;
                    lock (mbs) retval = mbs.AddIndividualAnimat(0, new mbsPosition { latitude = location.Latitude, longitude = location.Longitude, depth = 0 });
                    if (mbsRESULT.OK == retval) geos.Add(new Geo<float>(location.Latitude, location.Longitude, (float)(depth * Random.NextDouble())));
                }
                return geos;
            }, new ExecutionDataflowBlockOptions
            {
                TaskScheduler = TaskScheduler.Default,
                BoundedCapacity = -1,
                MaxDegreeOfParallelism = -1,
            });
            var bufferBlock = new BufferBlock<Geo<float>>();
            transformManyBlock.LinkTo(bufferBlock);
            var population = (int)Math.Round(area * species.PopulationDensity);
            result.TotalAnimats = population;
            const int blockSize = 100;
            while (population > 0)
            {
                transformManyBlock.Post(population > blockSize ? blockSize : population);
                population -= blockSize;
            }
            transformManyBlock.Complete();
            await transformManyBlock.Completion;
            //mbsResult = mbs.InitializeRun();
            //if (mbsRESULT.OK == mbsResult) while (mbsRUNSTATE.INITIALIZING == mbs.GetRunState()) Thread.Sleep(1);
            //else throw new AnimatInterfaceMMBSException("C3mbs::Initialize FATAL error " + mbs.ResultToTc(mbsResult));
            mbsResult = mbs.FinishRun();
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException("C3mbs::FinishRun FATAL error " + mbs.ResultToTc(mbsResult));

            IList<Geo<float>> animatGeos;
            if (bufferBlock.TryReceiveAll(out animatGeos))
                result.Locations.AddRange(animatGeos);
            return result;
        }
 /// <summary>
 /// Where is a segment within 'near' range of region
 /// </summary>
 /// <param name="segment">Segment to test</param>
 /// <param name="region">Region to test</param>
 /// <param name="near">Range, in radians</param>
 /// <returns>List of points that are within 'near' radians of region</returns>
 public static GeoArray Near(this GeoSegment segment, GeoArray region, double near)
 {
     return new GeoArray(region.Segments.Select(curSegment => segment.Intersection(curSegment, near)).Where(ret => ret != null));
 }
 /// <summary>
 /// Is a segment within 'near' range of region?
 /// </summary>
 /// <param name="segment"></param>
 /// <param name="region"></param>
 /// <param name="near"></param>
 /// <returns>True if any points are near the region</returns>
 public static bool IsNear(this GeoSegment segment, GeoArray region, double near)
 {
     return region.Segments.Select(curSegment => segment.Intersection(curSegment, near)).FirstOrDefault(ret => ret != null) != null;
 }
        public void PerimeterBounceToKML()
        {
            var jaxOpsArea = new GeoArray(
                new Geo(29.3590, -79.2195),
                new Geo(31.1627, -79.2195),
                new Geo(31.1627, -81.2789),
                new Geo(30.1627, -81.2789),
                new Geo(29.3590, -80.8789),
                new Geo(29.3590, -79.2195));

            var kml = new KMLRoot();
            var folder = new Folder("Jacksonville");
            jaxOpsArea.Placemark.name = "Jacksonville OpArea";
            jaxOpsArea.Placemark.Snippet = "The operational area";
            jaxOpsArea.Placemark.Snippet.maxLines = 1;
            folder.Add(jaxOpsArea.Placemark);

            GeoArray result = null;
            while (result == null)
            {
                try
                {
                    result = jaxOpsArea.PerimeterBounce(null, double.NaN, 1e8);
                }
                catch (PerimeterBounceException ex)
                {
                    Debug.WriteLine(ex.Message);
                    Debug.WriteLine("PerimeterBounce failed, retrying...");
                }
            }
            var startLocation = result[0];
            startLocation.Placemark.name = "Start location";
            startLocation.Placemark.Snippet = "The start of the track";
            startLocation.Placemark.Snippet.maxLines = 1;
            startLocation.Placemark.AddStyle(new IconStyle(System.Drawing.Color.Green) { Icon = new Icon() { href = @"http://www.clker.com/cliparts/q/y/S/n/A/V/green-pin-th.png" } });
            folder.Add(startLocation.Placemark);

            result.Placemark.name = "Platform track";
            result.Placemark.Snippet = "The track of the platform";
            result.Placemark.Snippet.maxLines = 1;
            result.Placemark.Geometry.AltitudeMode = AltitudeMode.clampedToGround;
            folder.Add(result.Placemark);

#if false
            var endPoint = result.Segments.Last()[1];
            if (!jaxOpsArea.Contains(endPoint))
            {
                var goodBounceSegment = result.Segments.ToArray()[result.Segments.Count() - 2];
                var goodBouncePoint = goodBounceSegment[0];
                var goodBounce = goodBouncePoint.Placemark;
                Debug.WriteLine("Test failed"); 
                goodBounce.name = string.Format("Last Good Bounce {0:000}", result.Segments.Count() - 1);
                Debug.WriteLine(goodBounce.name);
                goodBounce.Snippet = string.Format("Lat: {0:0.#####} Lon: {1:0.#####}", goodBouncePoint.Latitude, goodBouncePoint.Longitude);
                goodBounce.Snippet.maxLines = 1;
                folder.Add(goodBounce);

                goodBounceSegment.Placemark.name = "Last good bounce segment";
                goodBounceSegment.Placemark.AddStyle(new LineStyle(System.Drawing.Color.Red, 5));
                folder.Add(goodBounceSegment.Placemark);

                var badBouncePoint = goodBounceSegment[1];
                var badBounce = badBouncePoint.Placemark;
                badBounce.name = string.Format("Bad Bounce {0:000}", result.Segments.Count());
                badBounce.Snippet = string.Format("Lat: {0:0.#####} Lon: {1:0.#####}", badBouncePoint.Latitude, badBouncePoint.Longitude);
                badBounce.Snippet.maxLines = 1;
                folder.Add(badBounce);
            }
            else Debug.WriteLine("Test passed");
            var segments = result.Segments.ToArray();
            for (var segmentIndex = 0; segmentIndex < segments.Length; segmentIndex++)
            {
                var bounce = segments[segmentIndex][1].Placemark;
                bounce.name = string.Format("Bounce {0:000}", segmentIndex + 1);
                bounce.Snippet = string.Format("Lat: {0:0.#####} Lon: {1:0.#####}", segments[segmentIndex][1].Latitude, segments[segmentIndex][1].Longitude);
                bounce.Snippet.maxLines = 1;
                folder.Add(bounce);
            }
#endif

            var endLocation = result[result.Length - 1];
            endLocation.Placemark.name = "End location";
            endLocation.Placemark.Snippet = "The end of the track";
            endLocation.Placemark.Snippet.maxLines = 1;
            endLocation.Placemark.AddStyle(new IconStyle(System.Drawing.Color.Red) { Icon = new Icon { href = @"http://www.clker.com/cliparts/Z/x/U/0/B/3/red-pin-th.png" } });
            folder.Add(endLocation.Placemark);

            kml.Document.Add(folder);

            var savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Perimeter Bounce Tests", "PerimeterBounce.kml");
            Debug.WriteLine("Saving KML...");
            kml.Save(savePath);
        }
 /// <summary>
 /// return true if at least one point of poly is inside region
 /// </summary>
 /// <param name="poly">Polygon to check</param>
 /// <param name="region">Closed region</param>
 /// <returns></returns>
 public static bool HasPointsInside(this GeoArray poly, GeoArray region)
 {
     return poly.Geos.Any(geo => geo.IsInside(region));
 }
 public static bool Intersects(this GeoArray geoPoly1, GeoArray geoPoly2)
 {
     return geoPoly1.Segments.Any(segment1 => geoPoly2.Segments.Any(segment1.Intersects));
 }