public static double HaversineDistance(CoordinatePoint pa, CoordinatePoint pb) { double R = 6371;//kilometers, otherwise 6371 for miles double dLat = toRadian(pa.Latitude.Value - pb.Latitude.Value); double dLon = toRadian(pa.Longitude.Value - pb.Longitude.Value); double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(toRadian(pa.Latitude.Value)) * Math.Cos(toRadian(pb.Latitude.Value)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a))); double d = R * c; return(d * 1000); //convert to meters }
public double DistanceTo(ProjectedPoint point) { if (Bouys.Count == 1) { CoordinatePoint bp = new CoordinatePoint(Bouys[0].Latitude, Bouys[0].Longitude, 0); return(CoordinatePoint.TwoDimensionalDistance(point.Easting, point.Northing, bp.Project().Easting, bp.Project().Northing)); } else if (Bouys.Count == 2) { CoordinatePoint a = new CoordinatePoint(Bouys[0].Latitude, Bouys[0].Longitude, 0); CoordinatePoint b = new CoordinatePoint(Bouys[1].Latitude, Bouys[1].Longitude, 0); return(GeometryHelper.DistancePointToLineSegment(a.Project().Easting, a.Project().Northing, b.Project().Easting, b.Project().Northing, point.Easting, point.Northing)); } else { throw new Exception("Not Implemented"); } }
private void LoadPaths(Race race) { DateTime start = race.UtcStart; DateTime end = race.UtcEnd; _paths = new List<List<ColoredCoordinatePoint>>(); foreach (Boat b in race.Boats) { List<ColoredCoordinatePoint> points = new List<ColoredCoordinatePoint>(); Color c = Color.FromArgb(b.Color); SkipperDataSet.SensorReadingsDataTable dt = b.GetSensorReadings(start, end); for(int i=0;i<dt.Rows.Count;i++) { CoordinatePoint cp = new CoordinatePoint(new Coordinate(((SkipperDataSet.SensorReadingsRow)dt.Rows[i]).latitude), new Coordinate(((SkipperDataSet.SensorReadingsRow)dt.Rows[i]).longitude), ((SkipperDataSet.SensorReadingsRow)dt.Rows[i]).altitude); points.Add(new ColoredCoordinatePoint(cp, c)); } _paths.Add(points); } }
private void LoadBoatTracks() { _boatTracks = new Dictionary<ReplayBoat, SortedList<DateTime, ProjectedPoint>>(); foreach (ReplayBoat boat in Replay.Boats) { var points = from r in boat.SensorReadings orderby r.datetime ascending select r; SortedList<DateTime, ProjectedPoint> linePoints = new SortedList<DateTime, ProjectedPoint>(); foreach (var point in points) { CoordinatePoint cp = new CoordinatePoint(new Coordinate(point.latitude), new Coordinate(point.longitude), 0); ProjectedPoint pp = cp.Project(); if (!linePoints.ContainsKey(point.datetime)) { linePoints.Add(point.datetime, pp); } } _boatTracks.Add(boat, linePoints); } }
public void Move(DateTime time,Course course,float windDirection,DateTime raceStart) { //cheat and jump to the time for the very first move. //kindof hacky, but it keeps the user from having to wait for the boats to get //intialized when the race starts. Also, we probably don't want stats for <race time if (!_positionInitialized) { while (_boatDataRows[_currentBoatDataRow].datetime < raceStart && _currentBoatDataRow < _boatDataRows.Count - 2) { _currentBoatDataRow++; } //if (_currentBoatDataRow > 0) //{ // _currentBoatDataRow = _currentBoatDataRow - 1; //} _positionInitialized = true; } windAngle = windDirection; if (_lastUpdate == null) { _lastUpdate = time; } CoordinatePoint cp; ProjectedPoint current=null; CoordinatePoint np; ProjectedPoint next=null; long ticksBetween; long actualTicks; double percent=0.0; //bool changedIndex = false; bool doMove = false; if (_lastUpdate.Ticks < time.Ticks && _currentBoatDataRow < _boatDataRows.Count - 2) { doMove = true; direction = BoatDirection.Forward; while (_boatDataRows[_currentBoatDataRow].datetime < time && _currentBoatDataRow < _boatDataRows.Count - 2) { _currentBoatDataRow++; //changedIndex = true; if ((_lowWaterMark == null || _highWaterMark == null) || (time < _lowWaterMark || time > _highWaterMark)) { cp = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow + 1].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow + 1].longitude), 0); current = cp.Project(); np = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow].longitude), 0); next = np.Project(); ProjectedPoint = current; if (_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) < course.Route.Count) { NavigateCourse(_boatDataRows[_currentBoatDataRow].datetime, course, cp, np); } double distance = CoordinatePoint.TwoDimensionalDistance(current.Easting, current.Northing, next.Easting, next.Northing); TimeSpan ts = _boatDataRows[_currentBoatDataRow + 1].datetime - _boatDataRows[_currentBoatDataRow].datetime; double kmh = ((distance / 1000.0) / ts.TotalHours); speed = (float)kmh; //float oldWindAngle = RelativeAngleToWind; arrowAngle = (float)AngleHelper.FindAngle(current, next); float newWindAngle = RelativeAngleToWind; if (CurrentRacingStatus == RacingStatus.Racing) { float deadZone = MathHelper.PiOver4 / 2f;//use to be /4f; Tack.TackDirection newTack = Tack.TackDirection.Undetermined; if (newWindAngle < -deadZone && newWindAngle > -MathHelper.Pi + deadZone) { newTack = Tack.TackDirection.Starboard; } else if (newWindAngle > deadZone && newWindAngle < MathHelper.Pi - deadZone) { newTack = Tack.TackDirection.Port; } if (newTack != Tack.TackDirection.Undetermined && (_tacks.Count - 1 < _currentTackIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) || _tacks[_currentTackIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime)].Direction != newTack)) { PerformTack(_boatDataRows[_currentBoatDataRow].datetime); } } //set the current and previous marks if (_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) < course.Route.Count) { _currentMark = course.Route[_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime)]; } else { _currentMark = null; } if (_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) > 0 && course.Route.Count > 0) { _previousMark = course.Route[_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) - 1]; } else { _previousMark = null; } UpdateStatistics(_boatDataRows[_currentBoatDataRow].datetime, distance / 1000.0); Thread.Sleep(0); } } } else if (_lastUpdate.Ticks > time.Ticks && _currentBoatDataRow > 0) { doMove = true; direction = BoatDirection.Backwards; while (_boatDataRows[_currentBoatDataRow].datetime > time && _currentBoatDataRow > 1) { _currentBoatDataRow--; //changedIndex = true; if ((_lowWaterMark == null || _highWaterMark == null) || (time < _lowWaterMark || time > _highWaterMark)) { cp = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow - 1].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow - 1].longitude), 0); current = cp.Project(); np = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow].longitude), 0); next = np.Project(); //ProjectedPoint = cp.Project(); //double distance = CoordinatePoint.TwoDimensionalDistance(current.easting, current.northing, next.easting, next.northing); //TimeSpan ts = _boatDataRows[_currentBoatDataRow].datetime - _boatDataRows[_currentBoatDataRow - 1].datetime; //double kmh = ((distance / 1000.0) / ts.TotalHours); //speed = (float)kmh; arrowAngle = (float)AngleHelper.FindAngle(current, next); //UpdateStatistics(_boatDataRows[_currentBoatDataRow].datetime, distance / 1000.0); Thread.Sleep(0); } } } //set the current and previous marks if (_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) < course.Route.Count) { _currentMark = course.Route[_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime)]; } else { _currentMark = null; } if (_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) > 0 && course.Route.Count > 0) { _previousMark = course.Route[_currentMarkIndex.GetValue(_boatDataRows[_currentBoatDataRow].datetime) - 1]; } else { _previousMark = null; } if (doMove && _currentBoatDataRow > 0 && _currentBoatDataRow < _boatDataRows.Count - 2) { int currentOffset; if (direction == BoatDirection.Forward) { currentOffset = -1; } else { currentOffset = 1; } cp = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow + currentOffset].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow + currentOffset].longitude), 0); current = cp.Project(); np = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow].longitude), 0); next = np.Project(); CoordinatePoint pp = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow - currentOffset].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow - currentOffset].longitude), 0); ProjectedPoint previous = pp.Project(); ticksBetween = _boatDataRows[_currentBoatDataRow].datetime.Ticks - _boatDataRows[_currentBoatDataRow + currentOffset].datetime.Ticks; actualTicks = time.Ticks - _boatDataRows[_currentBoatDataRow + currentOffset].datetime.Ticks; percent = (double)actualTicks / (double)ticksBetween; double northingDiff = next.Northing - current.Northing; double eastingDiff = next.Easting - current.Easting; double northing = current.Northing + (northingDiff * percent); double easting = current.Easting + (eastingDiff * percent); ProjectedPoint actual = new ProjectedPoint(); actual.Easting = easting; actual.Northing = northing; ProjectedPoint = actual; double distance = CoordinatePoint.TwoDimensionalDistance(current.Easting, current.Northing, next.Easting, next.Northing); TimeSpan ts = new TimeSpan(ticksBetween); double kmh = ((distance / 1000.0) / ts.TotalHours); speed = (float)kmh; if (Math.Abs(kmh) > 2) { float startingAngle = (float)AngleHelper.FindAngle(previous, current); float desiredAngle = (float)AngleHelper.FindAngle(next, current); desiredAngle = AngleHelper.NormalizeAngle(desiredAngle); float deltaAngle = AngleHelper.AngleDifference(startingAngle, desiredAngle); arrowAngle = startingAngle + (deltaAngle * (float)percent); arrowAngle = AngleHelper.NormalizeAngle(arrowAngle); } SetHeel(time,kmh); SetSailCurve(time); SetBoomAngle(time); //if (changedIndex) //{ // _updateStatistics(); //} _lastUpdate = time; } else if(_currentBoatDataRow==0||_currentBoatDataRow==_boatDataRows.Count-1) { ProjectedPoint = new CoordinatePoint(new Coordinate(_boatDataRows[_currentBoatDataRow].latitude), new Coordinate(_boatDataRows[_currentBoatDataRow].longitude), 0).Project(); } if (_lowWaterMark==null||time < _lowWaterMark) { _lowWaterMark = time; } if (_highWaterMark == null || time > _highWaterMark) { _highWaterMark = time; } }
private void NavigateCourse(DateTime time, Course course,CoordinatePoint a,CoordinatePoint b) { //if (course.Route[CurrentMarkIndex.GetValue(time)].DistanceTo(location.Project()) < _markRoundDistance) //{ // CurrentMarkIndex.AddValue(time, CurrentMarkIndex.GetValue(time) + 1); // #warning possible bad increment of tack count // //not sure this should increment tack count, technically rounding a mark is not a tack. // if (CurrentMarkIndex.GetValue(time) < course.Route.Count) // { // PerformTack(time); // } //} Mark previous = null; Mark next = null; if (CurrentMarkIndex.GetValue(time) > 0) { previous = course.Route[CurrentMarkIndex.GetValue(time) - 1]; } if (CurrentMarkIndex.GetValue(time) < course.Route.Count - 1) { next = course.Route[CurrentMarkIndex.GetValue(time) + 1]; } if (course.Route[CurrentMarkIndex.GetValue(time)].IsRounding(a.Project(),b.Project(),previous,next)) { CurrentMarkIndex.AddValue(time, CurrentMarkIndex.GetValue(time) + 1); if (CurrentMarkIndex.GetValue(time) < course.Route.Count) { PerformTack(time); } } }
private void LakeResizeControl_Paint(object sender, PaintEventArgs e) { e.Graphics.FillRectangle(Brushes.White, 0, 0, this.Width, this.Height); if (_lake != null) { CoordinatePoint a2 = new CoordinatePoint(new Coordinate(_lake.South), new Coordinate(_lake.East), 0); CoordinatePoint b2 = new CoordinatePoint(new Coordinate(_lake.North), new Coordinate(_lake.West), 0); //Point br = this.CoordinatesToScreen(new CoordinatePoint(new Coordinate(_lake.South), new Coordinate(_lake.East), 0)); Point tl = CoordinatesToScreen(b2); Point br = CoordinatesToScreen(a2); Point tr = new Point(br.X, tl.Y); Point bl = new Point(tl.X, br.Y); Rectangle bounds = new Rectangle(tl.X, tl.Y, br.X - tl.X, br.Y - tl.Y); e.Graphics.FillRectangle(Brushes.DarkBlue, bounds); if (_satelite != null) { e.Graphics.DrawImage(_satelite, bounds); } if (_gpsBoundsNorthWest != null && _gpsBoundsSouthEast != null) { Point gpsTl = CoordinatesToScreen(_gpsBoundsNorthWest); Point gpsBr = CoordinatesToScreen(_gpsBoundsSouthEast); e.Graphics.DrawRectangle(Pens.Red, gpsTl.X, gpsTl.Y, gpsBr.X - gpsTl.X, gpsBr.Y - gpsTl.Y); } if (_mouseDown) { CoordinatePoint p = ScreenToCoordinates(_mousePosition); Point test = CoordinatesToScreen(p); e.Graphics.FillRectangle(Brushes.Red, test.X - 1, test.Y - 1, 2, 2); switch (_selectedCorner) { case SelectedCorner.BottomLeft: bl = _mousePosition; tl.X = _mousePosition.X; br.Y = _mousePosition.Y; break; case SelectedCorner.BottomRight: br = _mousePosition; tr.X = _mousePosition.X; bl.Y = _mousePosition.Y; break; case SelectedCorner.TopLeft: tl = _mousePosition; bl.X = _mousePosition.X; tr.Y = _mousePosition.Y; break; case SelectedCorner.TopRight: tr = _mousePosition; br.X = _mousePosition.X; tl.Y = _mousePosition.Y; break; } bounds = new Rectangle(tl.X, tl.Y, tr.X - tl.X, br.Y - tl.Y); } Pen outlinePen = new Pen(Brushes.Blue, 2); e.Graphics.DrawRectangle(outlinePen, bounds); e.Graphics.FillEllipse(Brushes.Orange, tl.X - 3, tl.Y - 3, 6, 6); e.Graphics.FillEllipse(Brushes.Orange, br.X - 3, br.Y - 3, 6, 6); e.Graphics.FillEllipse(Brushes.Orange, tr.X - 3, tr.Y - 3, 6, 6); e.Graphics.FillEllipse(Brushes.Orange, bl.X - 3, bl.Y - 3, 6, 6); } }
public void SetGpsBounds(CoordinatePoint northWest, CoordinatePoint southEast) { _gpsBoundsNorthWest = northWest; _gpsBoundsSouthEast = southEast; }
private void lakePNL_Paint(object sender, PaintEventArgs e) { CoordinatePoint a2 = new CoordinatePoint(new Coordinate(_lake.South), new Coordinate(_lake.East),0); CoordinatePoint b2 = new CoordinatePoint(new Coordinate(_lake.North), new Coordinate(_lake.West),0); Point br=this.CoordinatesToScreen(a2); Point tl = this.CoordinatesToScreen(b2); if (_cachedPanel == null) { _cachedPanel = new Bitmap(lakePNL.Width, lakePNL.Height); _cachedPanelWithBoats = new Bitmap(lakePNL.Width, lakePNL.Height); Graphics pg = Graphics.FromImage(_cachedPanel); Graphics pgwb = Graphics.FromImage(_cachedPanelWithBoats); pg.FillRectangle(Brushes.White, 0, 0, lakePNL.Width, lakePNL.Height); if (_image == null) { pg.FillRectangle(Brushes.DarkBlue, tl.X, tl.Y, br.X - tl.X, br.Y - tl.Y); } else { pg.DrawImage(_image, tl.X, tl.Y, br.X - tl.X, br.Y - tl.Y); } pgwb.DrawImage(_cachedPanel, 0, 0); foreach (List<ColoredCoordinatePoint> points in _paths) { int skip = 1; if (points.Count >= skip + 1) { Color c = points[0].Color; for (int i = 0; i < points.Count - skip; i = i + skip) { pgwb.DrawLine(new Pen(c), CoordinatesToScreen(points[i].Point), CoordinatesToScreen(points[i + skip].Point)); } } } } Bitmap temp = new Bitmap(lakePNL.Width, lakePNL.Height); Graphics gt = Graphics.FromImage(temp); if (showBoatsCB.Checked) { gt.DrawImage(_cachedPanelWithBoats,0,0); } else { gt.DrawImage(_cachedPanel, 0, 0); } if (_mouseDown && zoomInCB.Checked) { int lowX, highX, lowY, highY; if (_zoomFirstPoint.X < _zoomSecondPoint.X) { lowX = _zoomFirstPoint.X; highX = _zoomSecondPoint.X; } else { highX = _zoomFirstPoint.X; lowX = _zoomSecondPoint.X; } if (_zoomFirstPoint.Y < _zoomSecondPoint.Y) { lowY = _zoomFirstPoint.Y; highY = _zoomSecondPoint.Y; } else { highY = _zoomFirstPoint.Y; lowY = _zoomSecondPoint.Y; } Pen ZoomPen = new Pen(Color.Green, 2f); gt.DrawRectangle(ZoomPen, new Rectangle(lowX, lowY, highX - lowX, highY - lowY)); } List<Bouy> bouys = new List<Bouy>(); foreach (object o in marksLB.Items) { bouys.AddRange(((Mark)o).Bouys); } Point? previous = null; foreach (object o in routeLB.Items) { Mark currentMark = (Mark)o; int xSum = 0; int ySum = 0; List<Point> bouyPoints = new List<Point>(); foreach (Bouy b in currentMark.Bouys) { Point p = CoordinatesToScreen(new CoordinatePoint(b.Latitude, b.Longitude, 0)); bouyPoints.Add(p); xSum = xSum + p.X; ySum = ySum + p.Y; } Point current = new Point(xSum / currentMark.Bouys.Count, ySum / currentMark.Bouys.Count); if (bouyPoints.Count > 1) { foreach (Point p in bouyPoints) { gt.DrawLine(Pens.Green, current, p); } } if (previous != null) { gt.DrawLine(Pens.Yellow, current, (Point)previous); } previous = current; } foreach (Bouy b in bouys) { Point p=CoordinatesToScreen(new CoordinatePoint(b.Latitude,b.Longitude,0)); if (_selectedBouy != null && b.Id == _selectedBouy.Id) { gt.FillEllipse(Brushes.Red, new Rectangle(p.X - 5, p.Y - 5, 10, 10)); } else { gt.FillEllipse(Brushes.Orange, new Rectangle(p.X - 4, p.Y - 4, 8, 8)); } } e.Graphics.DrawImage(temp, 0, 0); }
private void SetOffsets() { _placeHolderCP = new CoordinatePoint(new Coordinate(Replay.Race.Lake.South), new Coordinate(Replay.Race.Lake.West), 0.0); _xOffset = 0f; _zOffset = 0f; //ProjectedPoint.projectedPointToWorld = new ProjectedPointToWorld(this.ProjectedPointToWorld); //CoordinatePoint.ProjectedPoint.projectedPointFromWorld = new ProjectedPointFromWorld(this.ProjectedPointFromWorld); if (this.Race.Lake.BottomLeftInMeters.Zone != this.Race.Lake.TopRightInMeters.Zone) { double zoneSize = this.Race.Lake.East - this.Race.Lake.West; if (zoneSize > 6.0) { CoordinatePoint.LongitudeZoneSize = zoneSize; } CoordinatePoint.LongitudeOffset = this.Race.Lake.West; } if (ProjectedPointToWorld(this.Race.Lake.BottomLeftInMeters).X < 0 && ProjectedPointToWorld(this.Race.Lake.TopRightInMeters).X < 0) { _xOffset = -(ProjectedPointToWorld(this.Race.Lake.TopRightInMeters).X * 2f); } else if (ProjectedPointToWorld(this.Race.Lake.BottomLeftInMeters).X > 0 && ProjectedPointToWorld(this.Race.Lake.TopRightInMeters).X > 0) { _xOffset = ProjectedPointToWorld(this.Race.Lake.BottomLeftInMeters).X; } if (ProjectedPointToWorld(this.Race.Lake.BottomLeftInMeters).Z < 0 && ProjectedPointToWorld(this.Race.Lake.TopRightInMeters).Z < 0) { _zOffset = -(ProjectedPointToWorld(this.Race.Lake.TopRightInMeters).Z * 2f); } else if (ProjectedPointToWorld(this.Race.Lake.BottomLeftInMeters).Z > 0 && ProjectedPointToWorld(this.Race.Lake.TopRightInMeters).Z > 0) { _zOffset = ProjectedPointToWorld(this.Race.Lake.BottomLeftInMeters).Z; } }
private Point CoordinatesToScreen(CoordinatePoint point) { Point off = Offset; Point p = ScaleCoordinatesToScreen(point); p.X = p.X + off.X; p.Y = p.Y + off.Y; return p; }
//private void DrawMouseInstructions(TimeSpan time, float viewportWidth, float viewportHeight) //{ // //if (time < new TimeSpan(0, 0, 12) && viewportWidth >= 320 && viewportHeight >= 240) // //{ // // _batch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState); // // string instructions; // // Texture2D texture; // // float maxBackgroundAlpha = 0.3f; // // float backgroundAlpha = maxBackgroundAlpha; // // float messageAlpha = 1f; // // if (time < new TimeSpan(0, 0, 4)) // // { // // if (time < new TimeSpan(0, 0, 1)) // // { // // backgroundAlpha = ((float)time.Milliseconds / 1000) * maxBackgroundAlpha; // // messageAlpha = ((float)time.Milliseconds / 1000); // // } // // else if (time > new TimeSpan(0, 0, 3)) // // { // // messageAlpha = ((float)(1000 - time.Milliseconds) / 1000); // // } // // //left click // // instructions = "Left click and drag to rotate the camera."; // // texture = _mouseLeftTexture; // // } // // else if (time < new TimeSpan(0, 0, 8)) // // { // // if (time < new TimeSpan(0, 0, 5)) // // { // // messageAlpha = ((float)time.Milliseconds / 1000); // // } // // else if (time > new TimeSpan(0, 0, 7)) // // { // // messageAlpha = ((float)(1000 - time.Milliseconds) / 1000); // // } // // //right click // // instructions = "Right click and drag to zoom in and out."; // // texture = _mouseRightTexture; // // } // // else if (time < new TimeSpan(0, 0, 12)) // // { // // if (time < new TimeSpan(0, 0, 9)) // // { // // messageAlpha = ((float)time.Milliseconds / 1000); // // } // // else if (time > new TimeSpan(0, 0, 11)) // // { // // backgroundAlpha = ((float)(1000 - time.Milliseconds) / 1000) * maxBackgroundAlpha; // // messageAlpha = ((float)(1000 - time.Milliseconds) / 1000); // // } // // //double click // // instructions = "Double click on a boat to follow it."; // // if (time.Seconds % 2 == 0) // // { // // texture = _mouseLeftTexture; // // } // // else // // { // // texture = _mouseTexture; // // } // // } // // else // // { // // throw new Exception("Unknown instruction state"); // // } // // //find the dimensions of the text and image // // float imageWidth = (float)texture.Width; // // float imageHeight = (float)texture.Height; // // float fontScale = ScaleFontToFitWidth(instructions, viewportWidth - imageWidth - 50); // // float instructionsWidth = _font.MeasureString(instructions).X * fontScale; // // float instructionsHeight = _font.MeasureString(instructions).Y * fontScale; // // //find the height and width of our message box // // float height = imageHeight * 1.5f; // // float width = viewportWidth; // // //draw the gray background // // _line.ClearVectors(); // // _line.Colour = new Color(new Vector4(1f, 1f, 1f, backgroundAlpha)); // // _line.Thickness = height; // // _line.AddVector(new Vector2(0, viewportHeight - height)); // // _line.AddVector(new Vector2(viewportWidth, viewportHeight - height)); // // _line.Render(_batch); // // //draw thew mouse texture // // _batch.Draw(texture, new Vector2(25, (viewportHeight - height) + (height - imageHeight) / 2), new Color(1f, 1f, 1f, messageAlpha)); // // //draw the instructions text // // _batch.DrawString(_font, instructions, new Vector2(25 + imageWidth + 25, (viewportHeight - height) + (height - instructionsHeight) / 2), new Color(1f, 1f, 1f, messageAlpha), 0.0f, new Vector2(0, 0), fontScale, SpriteEffects.None, 0); // // _batch.End(); // //} //} //private void DrawLabelBox(Vector2 boatLocation, SpriteBatch batch, System.Drawing.Color color, List<string> text, ref List<BoundingBox> otherBoxes, float viewportWidth, float viewportHieght) //{ // //float hpad = 5; // //float vpad = 2.5f; // //float width = 0; // //float height = 0; // //float lineHeight = 0; // //Color normalTextColor = Color.Black; // //float fontScale = 0.5f; // //foreach (string s in text) // //{ // // Vector2 size = _font.MeasureString(s); // // size = size * fontScale; // // if (size.X + (2 * hpad) > width) // // { // // width = size.X + (2 * hpad); // // } // // if (size.Y + (2 * vpad) > lineHeight) // // { // // lineHeight = size.Y + (2 * vpad); // // } // //} // //height = lineHeight * text.Count; // ////find an appropriate offset so that the label is towards the outer edge of the viewport // //Vector2 labelLocation = new Vector2(0f, 0f); // //Vector2 labelOffset = boatLocation - new Vector2(viewportWidth / 2f, viewportHieght / 2f); // //labelOffset.X = (labelOffset.X / (viewportWidth / 2f)) * 200f; // //labelOffset.Y = (labelOffset.Y / (viewportHieght / 2f)) * 200f; // ////use the offset to figure out where we would LIKE to put the label // //labelLocation.X = boatLocation.X + labelOffset.X - (width / 2f); // //labelLocation.Y = boatLocation.Y + labelOffset.Y - (height / 2f) - 50; // ////check and make sure we're not drawing the label off the screen // ////if we are, fix it // //if (labelLocation.X < 0) // // labelLocation.X = 0; // //if (labelLocation.X + width > viewportWidth) // // labelLocation.X = viewportWidth - width; // //if (labelLocation.Y > viewportHieght) // // labelLocation.Y = viewportHieght; // //if (labelLocation.Y - height < 0) // // labelLocation.Y = height; // //////see if it's a valid place to put it // //bool locationSet = CheckBounds(otherBoxes, labelLocation, width, height, viewportWidth, viewportWidth); // //float offset = 5; // ////we intentionally exhause all possibilities looking "up" before we look "down" // ////to avoid the labels jumping around when it gets stuck on another label // ////if it's not valid, look "up" for a clear spot // //if (!locationSet) // //{ // // while (offset < viewportHieght) // // { // // if (CheckBounds(otherBoxes, labelLocation + new Vector2(0, -offset), width, height, viewportWidth, viewportWidth)) // // { // // labelLocation = labelLocation + new Vector2(0, -offset); // // locationSet = true; // // break; // // } // // offset = offset + 5; // // } // //} // ////if it's still not valid, look "down" for a clear spot // //if (!locationSet) // //{ // // offset = 5; // // while (offset < viewportHieght) // // { // // //up // // if (CheckBounds(otherBoxes, labelLocation + new Vector2(0, offset), width, height, viewportWidth, viewportWidth)) // // { // // labelLocation = labelLocation + new Vector2(0, offset); // // locationSet = true; // // break; // // } // // offset = offset + 5; // // } // //} // ////if we found a spot draw the label // //if (locationSet) // //{ // // //figure out where the line should hit the label box, and what borders to draw // // Vector2 labelConnectPoint = new Vector2(); // // if (boatLocation.X < labelLocation.X) // // { // // labelConnectPoint.X = labelLocation.X; // // } // // else if (boatLocation.X >= labelLocation.X && boatLocation.X <= labelLocation.X + width) // // { // // labelConnectPoint.X = boatLocation.X; // // } // // else if (boatLocation.X > labelLocation.X) // // { // // labelConnectPoint.X = labelLocation.X + width; // // } // // if (boatLocation.Y < labelLocation.Y - height) // // { // // labelConnectPoint.Y = labelLocation.Y - height; // // } // // else if (boatLocation.Y >= labelLocation.Y - height && boatLocation.Y <= labelLocation.Y) // // { // // labelConnectPoint.Y = boatLocation.Y; // // } // // else if (boatLocation.Y > labelLocation.Y) // // { // // labelConnectPoint.Y = labelLocation.Y; // // } // // //background // // _line.ClearVectors(); // // _line.Colour = new Color(new Vector4(1f, 1f, 1f, 0.4f)); // // _line.Thickness = height; // // _line.AddVector(labelLocation + new Vector2(0, -height)); // // _line.AddVector(labelLocation + new Vector2(width, -height)); // // _line.Render(batch); // // //pointer // // _line.ClearVectors(); // // _line.Colour = color; // // _line.Thickness = 1f; // // _line.AddVector(boatLocation); // // _line.AddVector(labelConnectPoint); // // _line.Render(batch); // // //border // // _line.ClearVectors(); // // _line.Colour = color; // // _line.Thickness = 2f; // // _line.AddVector(labelLocation); // // _line.AddVector(new Vector2(labelLocation.X, labelLocation.Y - height)); // // _line.AddVector(new Vector2(labelLocation.X + width, labelLocation.Y - height)); // // _line.Render(batch); // // //draw our text // // for (int i = 0; i < text.Count; i++) // // { // // Color c; // // if (i == 0) // // { // // c = color; // // } // // else // // { // // c = normalTextColor; // // } // // Vector2 pos = new Vector2(labelLocation.X + hpad, (labelLocation.Y - height) + (i * lineHeight) + vpad); // // _batch.DrawString(_font, text[i], pos, c, 0.0f, new Vector2(0, 0), fontScale, SpriteEffects.None, 0); // // } // // //add the bounding box for this label to the collection so other labels can avoid us // // BoundingBox b = new BoundingBox(); // // b.Min = new Vector3(labelLocation.X, labelLocation.Y, -1); // // b.Max = new Vector3(labelLocation.X + width, labelLocation.Y + height, 1); // // otherBoxes.Add(b); // //} //} //private bool CheckBounds(List<BoundingBox> obstacles, Vector2 position, float width, float height, float viewportWidth, float viewportHeight) //{ // if (position.X >= 0 && position.X <= viewportWidth && position.Y >= 0 && position.Y <= viewportHeight && position.X + width >= 0 && position.X + width <= viewportWidth && position.Y - height >= 0 && position.Y <= viewportHeight) // { // BoundingBox pb = new BoundingBox(); // pb.Min = new Vector3(position.X, position.Y, -1); // pb.Max = new Vector3(position.X + width, position.Y + height, 1); // foreach (BoundingBox b in obstacles) // { // if (b.Contains(pb) != ContainmentType.Disjoint) // { // return false; // } // } // return true; // } // else // { // //bounds go off the screen // return false; // } //} //private void DrawInstrument(InstrumentDrawing drawingType, System.Drawing.Color color, Vector3 location, float rotation, float startDistance, float length) //{ // //float tipSize = 0.05f; // //_instruments.World = Matrix.CreateRotationY(rotation) * Matrix.CreateTranslation(location); // //_instruments.Begin(); // //foreach (EffectPass pass in _instruments.CurrentTechnique.Passes) // //{ // // pass.Begin(); // // VertexPositionColor[] vs; // // vs = new VertexPositionColor[6]; // // vs[0].Position = new Vector3(startDistance, 0, 0); // // vs[0].Color = color; // // vs[1].Position = new Vector3(startDistance + length, 0, 0); // // vs[1].Color = color; // // if (drawingType == InstrumentDrawing.InwardArrow) // // { // // vs[2].Position = new Vector3(startDistance, 0, 0); // // vs[2].Color = color; // // vs[3].Position = new Vector3(startDistance + (tipSize * 2), 0, tipSize); // // vs[3].Color = color; // // vs[4].Position = new Vector3(startDistance, 0, 0); // // vs[4].Color = color; // // vs[5].Position = new Vector3(startDistance + (tipSize * 2), 0, -tipSize); // // vs[5].Color = color; // // } // // else if (drawingType == InstrumentDrawing.OutwardArrow) // // { // // vs[2].Position = new Vector3(startDistance + length, 0, 0); // // vs[2].Color = color; // // vs[3].Position = new Vector3(startDistance + length - (tipSize * 2), 0, tipSize); // // vs[3].Color = color; // // vs[4].Position = new Vector3(startDistance + length, 0, 0); // // vs[4].Color = color; // // vs[5].Position = new Vector3(startDistance + length - (tipSize * 2), 0, -tipSize); // // vs[5].Color = color; // // } // // _device.RenderState.DepthBufferEnable = false; // // _device.VertexDeclaration = VertexDeclarationHelper.Get(typeof(VertexPositionColor)); // // _device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vs, 0, 3); // // _device.RenderState.DepthBufferEnable = true; // // pass.End(); // //} // //_instruments.End(); //} //private bool IsBoatOnScreen(Vector2 b, IViewPort vp) //{ // return (b.X > 0 && b.X < vp.RenderTarget.Width && b.Y > 0 && b.Y < vp.RenderTarget.Height); //} private void SetOffsets() { _placeHolderCP = new CoordinatePoint(new Coordinate(Replay.Race.Lake.South), new Coordinate(Replay.Race.Lake.West), 0.0); _eastingOffset = 0; _northingOffset = 0; if (this.Race.Lake.BottomLeftInMeters.Zone != this.Race.Lake.TopRightInMeters.Zone) { double zoneSize = this.Race.Lake.East - this.Race.Lake.West; if (zoneSize > 6.0) { CoordinatePoint.LongitudeZoneSize = zoneSize; } CoordinatePoint.LongitudeOffset = this.Race.Lake.West; } if (this.Race.Lake.BottomLeftInMeters.Northing < 0 && this.Race.Lake.TopRightInMeters.Northing < 0) { _northingOffset = -(this.Race.Lake.TopRightInMeters.Northing * 2.0); } else if (this.Race.Lake.BottomLeftInMeters.Northing > 0 && this.Race.Lake.TopRightInMeters.Northing > 0) { _northingOffset = this.Race.Lake.BottomLeftInMeters.Northing; } if (this.Race.Lake.BottomLeftInMeters.Easting < 0 && this.Race.Lake.TopRightInMeters.Easting < 0) { _eastingOffset = -(this.Race.Lake.TopRightInMeters.Easting * 2.0); } else if (this.Race.Lake.BottomLeftInMeters.Easting > 0 && this.Race.Lake.TopRightInMeters.Easting > 0) { _eastingOffset = this.Race.Lake.BottomLeftInMeters.Easting; } }
public ColoredCoordinatePoint(CoordinatePoint point, Color color) { Point = point; Color = color; }
private Point CoordinatesToScreen(CoordinatePoint point) { Lake lake = _lake; if (_zoomed&&_zoomedLake!=null) { lake = _zoomedLake; } //find length and width of the scaled area double scaleWidth = Math.Abs(lake.West - lake.East); double scaleHeight = Math.Abs(lake.North - lake.South); double scale; //the ratio of panel width to scaled width int dimension = 0; //the smallest dimension of the panel //set the scale based on whichever dimension is the longest //(if they are equal it doesn't matter) if (scaleWidth > scaleHeight) { if ((lakePNL.Width / scaleWidth) * scaleHeight <= lakePNL.Height) { dimension = lakePNL.Width; scale = (double)dimension / scaleWidth; } else { dimension = lakePNL.Height; scale = (double)dimension / scaleHeight; } } else { if (((double)lakePNL.Height / scaleHeight) * scaleWidth <= lakePNL.Width) { dimension = lakePNL.Height; scale = (double)dimension / scaleHeight; } else { dimension = lakePNL.Width; scale = (double)dimension / scaleWidth; } } Point output = new Point(); output.X = (int)((point.Longitude.Value - lake.West) * scale); output.Y = (int)(scaleHeight * scale) - (int)((point.Latitude.Value - lake.South) * scale); return output; }
public static double HaversineDistance(CoordinatePoint pa, CoordinatePoint pb) { double R = 6371;//kilometers, otherwise 6371 for miles double dLat = toRadian(pa.Latitude.Value - pb.Latitude.Value); double dLon = toRadian(pa.Longitude.Value - pb.Longitude.Value); double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(toRadian(pa.Latitude.Value)) * Math.Cos(toRadian(pb.Latitude.Value)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a))); double d = R * c; return d*1000; //convert to meters }
private Point ScaleCoordinatesToScreen(CoordinatePoint point) { //find length and width of the scaled area double scaleWidth = Math.Abs(_lake.West - _lake.East); double scaleHeight = Math.Abs(_lake.North - _lake.South); double scale; //the ratio of panel width to scaled width int dimension = 0; //the smallest dimension of the panel //set the scale based on whichever dimension is the longest //(if they are equal it doesn't matter) if (scaleWidth > scaleHeight) { if ((this.Width / scaleWidth) * scaleHeight <= this.Height) { dimension = this.Width; scale = (double)dimension / scaleWidth; } else { dimension = this.Height; scale = (double)dimension / scaleHeight; } } else { if (((double)this.Height / scaleHeight) * scaleWidth <= this.Width) { dimension = this.Height; scale = (double)dimension / scaleHeight; } else { dimension = this.Width; scale = (double)dimension / scaleWidth; } } scale = scale / 1.5; Point output = new Point(); output.X = (int)((point.Longitude.Value - _lake.West) * scale); output.Y = (int)(scaleHeight * scale) - (int)((point.Latitude.Value - _lake.South) * scale); return output; }
public void BuildBoatPathCurve(ReplayBoat boat) { SortedList<int, int> tempBoatDataRowsCurveMap = new SortedList<int, int>(); List<Vector3> tempControlPoints = new List<Vector3>(); List<float> tempDistances = new List<float>(); List<Vector3> controlPoints = new List<Vector3>(); for (int i = 0; i < boat.SensorReadings.Count; i++) { CoordinatePoint cp = new CoordinatePoint(new Coordinate(boat.SensorReadings[i].latitude), new Coordinate(boat.SensorReadings[i].longitude), 0); controlPoints.Add(ProjectedPointToWorld(cp.Project())); } List<Vector3> curvePoints = BezierHelper.CreateSmoothedLine(controlPoints, out tempBoatDataRowsCurveMap, out tempControlPoints, out tempDistances); _boatDataRowsCurveMap[boat] = tempBoatDataRowsCurveMap; _boatPathCurve[boat] = new VertexPositionColor[(curvePoints.Count * 2) - 2]; _boatPathControlPoints[boat] = tempControlPoints; _boatDataRowsDistances[boat] = tempDistances; float maxWidth = 0.2f;//meters/coord divisor float minWidth = 0.01f;//meters/coord divisor float maxSpeed = 20f;//kmh //float minSpeed = 0f;//kmh int vertexIndex = 0; for (int i = 0; i < boat.SensorReadings.Count - 2; i++) { int curveStart = _boatDataRowsCurveMap[boat][i]; int curveEnd = _boatDataRowsCurveMap[boat][i + 1]; float startDistance = _boatDataRowsDistances[boat][i]; float endDistance = _boatDataRowsDistances[boat][i + 1]; float startSpeed = (startDistance / 1000) / (float)(boat.SensorReadings[i + 1].datetime - boat.SensorReadings[i].datetime).TotalHours; float endSpeed = (endDistance / 1000) / (float)(boat.SensorReadings[i + 2].datetime - boat.SensorReadings[i + 1].datetime).TotalHours; float speedDelta = endSpeed - startSpeed; int curvePointCount = curveEnd - curveStart; for (int c = curveStart; c < curveEnd; c++) { float percentThrough = ((float)c - (float)curveStart) / (float)curvePointCount; float speed = startSpeed + (percentThrough * speedDelta); float width = minWidth + ((speed / maxSpeed) * (maxWidth - minWidth)); width = maxWidth - width; float angleToNext = -(float)Math.Atan2(curvePoints[c + 1].Z - curvePoints[c].Z, curvePoints[c + 1].X - curvePoints[c].X); float angleRight = angleToNext + MathHelper.PiOver2; float angleLeft = angleToNext - MathHelper.PiOver2; float rightX = curvePoints[c].X + (float)Math.Cos(angleRight) * (width / 2f); float rightZ = curvePoints[c].Z - (float)Math.Sin(angleRight) * (width / 2f); VertexPositionColor right = new VertexPositionColor(); right.Position = new Vector3(rightX, 0, rightZ); _boatPathCurve[boat][vertexIndex] = right; vertexIndex++; float leftX = curvePoints[c].X + (float)Math.Cos(angleLeft) * (width / 2f); float leftZ = curvePoints[c].Z - (float)Math.Sin(angleLeft) * (width / 2f); VertexPositionColor left = new VertexPositionColor(); left.Position = new Vector3(leftX, 0, leftZ); _boatPathCurve[boat][vertexIndex] = left; vertexIndex++; } } }
private void LakeResizeControl_MouseMove(object sender, MouseEventArgs e) { if (_lake != null) { _mousePosition = new Point(e.X, e.Y); if (_mouseDown && _selectedCorner.HasValue) { this.Invalidate(); } else { double minDistance = 25.0; CoordinatePoint a2 = new CoordinatePoint(new Coordinate(_lake.South), new Coordinate(_lake.East), 0); CoordinatePoint b2 = new CoordinatePoint(new Coordinate(_lake.North), new Coordinate(_lake.West), 0); Point tl = CoordinatesToScreen(b2); Point br = CoordinatesToScreen(a2); Point tr = new Point(br.X, tl.Y); Point bl = new Point(tl.X, br.Y); double tlDistance = CoordinatePoint.TwoDimensionalDistance(_mousePosition.X, _mousePosition.Y, tl.X, tl.Y); double brDistance = CoordinatePoint.TwoDimensionalDistance(_mousePosition.X, _mousePosition.Y, br.X, br.Y); double trDistance = CoordinatePoint.TwoDimensionalDistance(_mousePosition.X, _mousePosition.Y, tr.X, tr.Y); double blDistance = CoordinatePoint.TwoDimensionalDistance(_mousePosition.X, _mousePosition.Y, bl.X, bl.Y); if (tlDistance <= brDistance && tlDistance <= trDistance && tlDistance <= blDistance && tlDistance<minDistance) { _selectedCorner = SelectedCorner.TopLeft; this.Cursor = Cursors.PanNW; } else if (brDistance <= tlDistance && brDistance <= trDistance && brDistance <= blDistance && brDistance<minDistance) { _selectedCorner = SelectedCorner.BottomRight; this.Cursor = Cursors.PanSE; } else if (trDistance <= tlDistance && trDistance <= brDistance && trDistance <= blDistance && trDistance<minDistance) { _selectedCorner = SelectedCorner.TopRight; this.Cursor = Cursors.PanNE; } else if (blDistance <= tlDistance && blDistance <= brDistance && blDistance <= trDistance && blDistance < minDistance) { _selectedCorner = SelectedCorner.BottomLeft; this.Cursor = Cursors.PanSW; } else { _selectedCorner = null; this.Cursor = Cursors.No; } } } }
private bool FindGpsBounds(ref CoordinatePoint nw, ref CoordinatePoint se, ref double alt) { double? minLat=null;// = double.MaxValue; double? maxLat = null;// = double.MinValue; double? minLong = null;// = double.MaxValue; double? maxLong = null;// = double.MinValue; //double altitude = 0; //int altcount = 0; foreach (AmphibianSoftware.VisualSail.Data.Boat b in _boats) { //bool increment=false; if (b.GpsMinimumLatitude!=null && (minLat==null || b.GpsMinimumLatitude < minLat)) { minLat = b.GpsMinimumLatitude; } if (b.GpsMaximumLatitude!=null && (maxLat==null || b.GpsMaximumLatitude > maxLat)) { maxLat = b.GpsMaximumLatitude; } if (b.GpsMinimumLongitude!=null && (minLong==null || b.GpsMinimumLongitude < minLong)) { minLong = b.GpsMinimumLongitude; } if (b.GpsMaximumLongitude!=null && (maxLong==null || b.GpsMaximumLongitude > maxLong)) { maxLong = b.GpsMaximumLongitude; } //if (r.altitude != 0) //{ // if (altitude == 0) // { // altitude = r.altitude; // } // else // { // altitude = ((altitude * altcount) + r.altitude) / (altcount + 1); // } // altcount++; //} //count++; } if (minLat!=null&&maxLat!=null&&minLong!=null&&maxLong!=null) { //alt = altitude; nw = new CoordinatePoint(new Coordinate((double)maxLat), new Coordinate((double)minLong), alt); se = new CoordinatePoint(new Coordinate((double)minLat), new Coordinate((double)maxLong), alt); return true; } else { return false; } }
public double DistanceTo(ProjectedPoint point) { if (Bouys.Count == 1) { CoordinatePoint bp = new CoordinatePoint(Bouys[0].Latitude, Bouys[0].Longitude, 0); return CoordinatePoint.TwoDimensionalDistance(point.Easting, point.Northing, bp.Project().Easting, bp.Project().Northing); } else if (Bouys.Count == 2) { CoordinatePoint a = new CoordinatePoint(Bouys[0].Latitude, Bouys[0].Longitude, 0); CoordinatePoint b = new CoordinatePoint(Bouys[1].Latitude, Bouys[1].Longitude, 0); return GeometryHelper.DistancePointToLineSegment(a.Project().Easting, a.Project().Northing, b.Project().Easting, b.Project().Northing, point.Easting, point.Northing); } else { throw new Exception("Not Implemented"); } }