/// <summary> /// Save move of a rover. We need to prevent hitting an active vessel. /// </summary> /// <param name="latitude"></param> /// <param name="longitude"></param> /// <returns>true if rover was moved, false otherwise</returns> private bool MoveSafely(double latitude, double longitude) { double altitude = GeoUtils.TerrainHeightAt(latitude, longitude, vessel.mainBody); if (FlightGlobals.ActiveVessel != null) { Vector3d newPos = vessel.mainBody.GetWorldSurfacePosition(latitude, longitude, altitude); Vector3d actPos = FlightGlobals.ActiveVessel.GetWorldPos3D(); double distance = Vector3d.Distance(newPos, actPos); if (distance <= 2400) { return(false); } } vessel.latitude = latitude; vessel.longitude = longitude; if (vessel.situation == Vessel.Situations.SPLASHED) { vessel.altitude = vesselHeightFromTerrain; } else { vessel.altitude = altitude + vesselHeightFromTerrain; } return(true); }
public double StraightPath() { double distanceToTarget = GeoUtils.GetDistance(startLatitude, startLongitude, targetLatitude, targetLongitude, mainBody.Radius); // if (distanceToTarget < 1000) return; double bearing = GeoUtils.InitialBearing(startLatitude, startLongitude, targetLatitude, targetLongitude); double altitude = GeoUtils.TerrainHeightAt(startLatitude, startLongitude, mainBody); int x = 0; int y = 0; Hex start = new Hex(startLatitude, startLongitude, altitude, bearing, x, y, this); tiles.Add(start); double straightPath = 0; // ScreenMessages.PostScreenMessage ("building straight " + DateTime.Now.ToString()); while (straightPath < distanceToTarget - 500) { GetNeighbours(x, y, false); Hex current = tiles.Find(t => (t.X == x && t.Y == y)); x += directions [0].X; y += directions [0].Y; Hex next = tiles.Find(t => (t.X == x && t.Y == y)); if (next.Altitude < 0 || ((next.Altitude - current.Altitude) > 500) || ((next.Altitude - current.Altitude) < -500)) { return(0); } straightPath += 1000; } Hex destination = tiles.Find(t => (t.X == x + directions [180].X) && (t.Y == y + directions [180].Y)); return(distanceToTarget); }
/// <summary> /// Find path to the target /// </summary> internal void FindPath() { double distanceToTarget = GeoUtils.GetDistance(startLatitude, startLongitude, targetLatitude, targetLongitude, mainBody.Radius); if (distanceToTarget < StepSize) { return; } double bearing = GeoUtils.InitialBearing(startLatitude, startLongitude, targetLatitude, targetLongitude); double altitude = GeoUtils.TerrainHeightAt(startLatitude, startLongitude, mainBody); int x = 0; int y = 0; Hex start = new Hex(startLatitude, startLongitude, altitude, bearing, x, y, this); tiles.Add(start); double straightPath = 0; while (straightPath < distanceToTarget) { GetNeighbours(x, y, false); x += directions[0].X; y += directions[0].Y; straightPath += StepSize; } Hex destination = tiles.Find(t => (t.X == x + directions[180].X) && (t.Y == y + directions[180].Y)); path = Path <Hex> .FindPath <Hex>(start, destination, distance, estimate); }
/// <summary> /// Decodes the path. /// </summary> /// <returns>The path.</returns> /// <param name="pathEncoded">Path encoded.</param> /// <param name="body">Body.</param> internal static List <Vector3d> DecodePath(string pathEncoded, CelestialBody body) { List <Vector3d> result = new List <Vector3d> (); if (pathEncoded == null || pathEncoded.Length == 0) { return(result); } // Path is compressed, decompress // For compatibility purposes only if (!pathEncoded.Contains(";")) { pathEncoded = LZString.decompressFromBase64(pathEncoded); } char[] separators = new char[] { ';' }; string[] wps = pathEncoded.Split(separators, StringSplitOptions.RemoveEmptyEntries); foreach (var wp in wps) { string[] latlon = wp.Split(':'); double latitude = double.Parse(latlon [0]); double longitude = double.Parse(latlon [1]); double altitude = GeoUtils.TerrainHeightAt(latitude, longitude, body); Vector3d localSpacePoint = body.GetWorldSurfacePosition(latitude, longitude, altitude); result.Add(localSpacePoint); } return(result); }
internal IEnumerable <Hex> GetNeighbours(int x, int y, bool passable = true) { var tile = tiles.Find(t => (t.X == x) && (t.Y == y)); if (tile == null) { return(null); } List <Hex> neighbours = new List <Hex>(); foreach (var direction in directions) { int dirX = direction.Value.X; int dirY = direction.Value.Y; var neighbour = tiles.Find(n => (n.X == tile.X + dirX) && (n.Y == tile.Y + dirY)); if (neighbour == null) { double[] coords = GeoUtils.GetLatitudeLongitude(tile.Latitude, tile.Longitude, tile.Bearing + direction.Key, StepSize, mainBody.Radius); double newBearing = GeoUtils.FinalBearing(tile.Latitude, tile.Longitude, coords[0], coords[1]); newBearing = (newBearing - direction.Key + 360) % 360; double altitude = GeoUtils.TerrainHeightAt(coords[0], coords[1], mainBody); neighbour = new Hex(coords[0], coords[1], altitude, newBearing, tile.X + dirX, tile.Y + dirY, this); } neighbours.Add(neighbour); tiles.Add(neighbour); } if (passable) { switch (tileTypes) { case TileTypes.Land | TileTypes.Ocean: return(neighbours.Where( n => ((n.Altitude - tile.Altitude) < StepSize / 2) && ((n.Altitude - tile.Altitude) > 0 - StepSize / 2) )); case TileTypes.Land: return(neighbours.Where( n => (n.Altitude >= 0 || !mainBody.ocean) && ((n.Altitude - tile.Altitude) < StepSize / 2) && ((n.Altitude - tile.Altitude) > 0 - StepSize / 2) )); case TileTypes.Ocean: return(neighbours.Where( n => (n.Altitude <= 0) )); default: return(neighbours); } } else { return(neighbours); } }
/// <summary> /// Decodes the path. /// </summary> /// <returns>The path.</returns> /// <param name="pathEncoded">Path encoded.</param> /// <param name="body">Body.</param> internal static List <Vector3d> DecodePath(string pathEncoded, CelestialBody body) { List <Vector3d> result = new List <Vector3d> (); if (pathEncoded == null || pathEncoded.Length == 0) { return(result); } // Path is compressed, decompress // For compatibility purposes only if (!pathEncoded.Contains(";")) { //pathEncoded = LZString.decompressFromBase64(pathEncoded); // Change LZString implementation of base64 to native functions // Replace # with forward slash (two forward slashes seems to be interpreted as a start of the comment when read from a save file) string temp = pathEncoded; var encodedBytes = System.Convert.FromBase64String(temp.Replace('#', '/')); temp = System.Text.Encoding.UTF8.GetString(encodedBytes); if (temp.Contains(":")) // backward compatibility for path encoded with LZString { pathEncoded = temp; } else { pathEncoded = LZString.decompressFromBase64(pathEncoded); } } char[] separators = new char[] { ';' }; string[] wps = pathEncoded.Split(separators, StringSplitOptions.RemoveEmptyEntries); foreach (var wp in wps) { string[] latlon = wp.Split(':'); double latitude = double.Parse(latlon [0]); double longitude = double.Parse(latlon [1]); double altitude = GeoUtils.TerrainHeightAt(latitude, longitude, body); Vector3d localSpacePoint = body.GetWorldSurfacePosition(latitude, longitude, altitude); result.Add(localSpacePoint); } return(result); }
internal IEnumerable <Hex> GetNeighbours(int x, int y, bool passable = true) { // Debug.Log (String.Format("bonvoyage - finding neighbours for {0}, {1}", x, y)); var tile = tiles.Find(t => (t.X == x) && (t.Y == y)); if (tile == null) { // Debug.Log ("bonvoyage - tile not found"); return(null); } List <Hex> neighbours = new List <Hex> (); foreach (var direction in directions) { int dirX = direction.Value.X; int dirY = direction.Value.Y; var neighbour = tiles.Find(n => (n.X == tile.X + dirX) && (n.Y == tile.Y + dirY)); if (neighbour == null) { // Debug.Log ("bonvoyage - neighbour not found"); double[] coords = GeoUtils.GetLatitudeLongitude(tile.Latitude, tile.Longitude, tile.Bearing + direction.Key, StepSize, mainBody.Radius); double newBearing = GeoUtils.FinalBearing(tile.Latitude, tile.Longitude, coords [0], coords [1]); newBearing = (newBearing - direction.Key + 360) % 360; double altitude = GeoUtils.TerrainHeightAt(coords [0], coords [1], mainBody); neighbour = new Hex(coords [0], coords [1], altitude, newBearing, tile.X + dirX, tile.Y + dirY, this); } neighbours.Add(neighbour); tiles.Add(neighbour); } if (passable) { return(neighbours.Where( n => (n.Altitude >= 0 || !mainBody.ocean) && ((n.Altitude - tile.Altitude) < StepSize / 2) && ((n.Altitude - tile.Altitude) > 0 - StepSize / 2) )); } else { return(neighbours); } }
public void FindPath() { double distanceToTarget = GeoUtils.GetDistance(startLatitude, startLongitude, targetLatitude, targetLongitude, mainBody.Radius); if (distanceToTarget < 1000) { return; } double bearing = GeoUtils.InitialBearing(startLatitude, startLongitude, targetLatitude, targetLongitude); double altitude = GeoUtils.TerrainHeightAt(startLatitude, startLongitude, mainBody); int x = 0; int y = 0; Hex start = new Hex(startLatitude, startLongitude, altitude, bearing, x, y, this); tiles.Add(start); double straightPath = 0; // ScreenMessages.PostScreenMessage ("building straight " + DateTime.Now.ToString()); while (straightPath < distanceToTarget - 500) { GetNeighbours(x, y, false); x += directions [0].X; y += directions [0].Y; straightPath += 1000; } Hex destination = tiles.Find(t => (t.X == x + directions [180].X) && (t.Y == y + directions [180].Y)); /* KSP.IO.File.AppendAllText<BonVoyage> ( * // String.Format("lat: {0}\nlon: {1}\nbea: {2}\n----\n", this.latitude, this.longitude, this.bearing), * String.Format("start: {0}, destination: {1}\n----\n", start.Id, destination.Id), * "path" * );*/ // ScreenMessages.PostScreenMessage ("started caclulation " + DateTime.Now.ToString()); path = Path <Hex> .FindPath <Hex> (start, destination, distance, estimate); ScreenMessages.PostScreenMessage("Path build"); }
/// <summary> /// Prevent crazy torpedoing active vessel :D /// </summary> /// <returns><c>true</c>, if rover was moved, <c>false</c> otherwise.</returns> /// <param name="latitude">Latitude.</param> /// <param name="longitude">Longitude.</param> private bool MoveSafe(double latitude, double longitude) { double altitude = GeoUtils.TerrainHeightAt(latitude, longitude, vessel.mainBody); if (FlightGlobals.ActiveVessel != null) { Vector3d newPos = vessel.mainBody.GetWorldSurfacePosition(latitude, longitude, altitude); Vector3d actPos = FlightGlobals.ActiveVessel.GetWorldPos3D(); double distance = Vector3d.Distance(newPos, actPos); if (distance <= 2400) { return(false); } // VesselRanges ranges = active.vesselRanges.GetSituationRanges(Vessel.Situations.LANDED || Vessel.Situations.FLYING); // vessel.GoOffRails (); // vessel.Load (); } vessel.latitude = latitude; vessel.longitude = longitude; vessel.altitude = altitude; return(true); }
public void Update() { if (lastUpdated.AddSeconds(1) > DateTime.Now) { return; } lastUpdated = DateTime.Now; double currentTime = Planetarium.GetUniversalTime(); foreach (var rover in activeRovers) { if (rover.vessel.isActiveVessel) { rover.status = "current"; continue; } if (!rover.bvActive || rover.vessel.loaded) { rover.status = "idle"; continue; } Vector3d vesselPos = rover.vessel.mainBody.position - rover.vessel.GetWorldPos3D(); Vector3d toKerbol = rover.vessel.mainBody.position - FlightGlobals.Bodies[0].position; double angle = Vector3d.Angle(vesselPos, toKerbol); // No moving at night, or when there's not enougth solar light if (angle >= 85 && rover.solarPowered) { rover.status = "awaiting sunlight"; rover.lastTime = currentTime; rover.BVModule.SetValue("lastTime", currentTime.ToString()); rover.vessel.protoVessel = new ProtoVessel(rover.vesselConfigNode, HighLogic.CurrentGame); continue; } double deltaT = currentTime - rover.lastTime; double deltaS = rover.averageSpeed * deltaT; double bearing = GeoUtils.InitialBearing( rover.vessel.latitude, rover.vessel.longitude, rover.targetLatitude, rover.targetLongitude ); rover.distanceTravelled += deltaS; if (rover.distanceTravelled >= rover.distanceToTarget) { rover.distanceTravelled = rover.distanceToTarget; rover.vessel.latitude = rover.targetLatitude; rover.vessel.longitude = rover.targetLongitude; rover.bvActive = false; rover.BVModule.SetValue("isActive", "False"); rover.BVModule.SetValue("distanceTravelled", rover.distanceToTarget.ToString()); rover.BVModule.GetNode("EVENTS").GetNode("Activate").SetValue("active", "True"); rover.BVModule.GetNode("EVENTS").GetNode("Deactivate").SetValue("active", "False"); if (autoDewarp) { TimeWarp.SetRate(0, false); ScreenMessages.PostScreenMessage(rover.vessel.vesselName + " has arrived to destination at " + rover.vessel.mainBody.name); } MessageSystem.Message message = new MessageSystem.Message( "Rover arrived", //------------------------------------------ rover.vessel.vesselName + " has arrived to destination\nLAT:" + rover.targetLatitude.ToString("F2") + "\nLON:" + rover.targetLongitude.ToString("F2") + "\nAt " + rover.vessel.mainBody.name + ". \n" + "Distance travelled: " + rover.distanceTravelled.ToString("N") + " meters", //------------------------------------------ MessageSystemButton.MessageButtonColor.GREEN, MessageSystemButton.ButtonIcons.COMPLETE ); MessageSystem.Instance.AddMessage(message); rover.status = "idle"; } else { int step = Convert.ToInt32(Math.Floor(rover.distanceTravelled / 1000)); double remainder = rover.distanceTravelled % 1000; if (step < rover.path.Count - 1) { bearing = GeoUtils.InitialBearing( rover.path[step].latitude, rover.path[step].longitude, rover.path[step + 1].latitude, rover.path[step + 1].longitude ); } else { bearing = GeoUtils.InitialBearing( rover.path[step].latitude, rover.path[step].longitude, rover.targetLatitude, rover.targetLongitude ); } double[] newCoordinates = GeoUtils.GetLatitudeLongitude( rover.path[step].latitude, rover.path[step].longitude, bearing, remainder, rover.vessel.mainBody.Radius ); rover.vessel.latitude = newCoordinates[0]; rover.vessel.longitude = newCoordinates[1]; rover.status = "roving"; } rover.vessel.altitude = GeoUtils.TerrainHeightAt(rover.vessel.latitude, rover.vessel.longitude, rover.vessel.mainBody); // rover.toTravel = rover.distanceToTarget - rover.distanceTravelled; rover.lastTime = currentTime; // Save data to protovessel rover.vesselConfigNode.SetValue("lat", rover.vessel.latitude.ToString()); rover.vesselConfigNode.SetValue("lon", rover.vessel.longitude.ToString()); rover.vesselConfigNode.SetValue("alt", rover.vessel.altitude.ToString()); rover.vesselConfigNode.SetValue("landedAt", rover.vessel.mainBody.theName); rover.BVModule.SetValue("distanceTravelled", (rover.distanceTravelled).ToString()); rover.BVModule.SetValue("lastTime", currentTime.ToString()); rover.vessel.protoVessel = new ProtoVessel(rover.vesselConfigNode, HighLogic.CurrentGame); } }