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)); }
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)); }