Exemplo n.º 1
0
 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");
     }
 }
Exemplo n.º 2
0
        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);
            }
        }
Exemplo n.º 3
0
        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++;
                }
            }
        }
Exemplo n.º 4
0
        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;
            }

        }
Exemplo n.º 5
0
        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);
                }
            }
        }
Exemplo n.º 6
0
 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");
     }
 }