private static int CompareByMass(ChangedPlanet a, ChangedPlanet b) { if (a == null) { if (b == null) { return(0); } else { return(-1); } } else { if (b == null) { return(1); } else { return(b.Mass.CompareTo(a.Mass)); } } }
public void DefaultSystem() { if (!File.Exists(KSPUtil.ApplicationRootPath + "/GameData/PlanetRandomizer/Resources/PlanetRandomizerDefault.cfg")) { print("Saving default system"); List <ChangedPlanet> tempPlanet = new List <ChangedPlanet>(); foreach (CelestialBody body in FlightGlobals.Bodies) { if (body.gameObject.name != "Sun") { ChangedPlanet cp = new ChangedPlanet(); cp.Name = body.gameObject.name; cp.Radius = body.Radius; cp.Mass = body.Mass; cp.RotationPeriod = body.rotationPeriod; cp.SemiMajorAxis = body.orbit.semiMajorAxis; cp.Eccentricity = body.orbit.eccentricity; cp.Inclination = body.orbit.inclination; cp.MeanAnomalyAtEpoch = body.orbit.meanAnomalyAtEpoch; cp.LAN = body.orbit.LAN; cp.ArgumentOfPeriapsis = body.orbit.argumentOfPeriapsis; cp.ReferenceBody = body.orbit.referenceBody.name; tempPlanet.Add(cp); } } PlanetDefault.Instance.Planets = tempPlanet.ToArray(); PlanetDefault.Instance.Save(KSPUtil.ApplicationRootPath + "/GameData/PlanetRandomizer/Resources/PlanetRandomizerDefault.cfg"); RebuildSystemDef(); } else { PlanetDefault.Load(KSPUtil.ApplicationRootPath + "/GameData/PlanetRandomizer/Resources/PlanetRandomizerDefault.cfg"); RebuildSystemDef(); } }
private void ChangeSystem() { print("Changing System"); System.Random rand = new System.Random(PlanetSettings.Instance.seed); CelestialBody sun = GetSun(); List <ChangedPlanet> tempPlanet = new List <ChangedPlanet>(); foreach (CelestialBody body in FlightGlobals.Bodies) { if (body.gameObject.name != "Sun") { ChangedPlanet cp = new ChangedPlanet(); cp.Name = body.gameObject.name; print("Changing " + cp.Name); double origRadius = body.Radius; if (body.name != "Kerbin" && body.pqsController != null) { cp.Radius = origRadius * Math.Pow(2, 2.0 * rand.NextDouble() - 1); } else { cp.Radius = origRadius; // Kerbin, gas giants, and stars don't change their radius } if (body.name == "Kerbin") { cp.Mass = body.Mass; // Kerbin doesn't change its mass } else if (body.Mass >= sun.Mass * 0.1) { cp.Mass = sun.Mass * 0.1 * Math.Pow(2, 2.0 * rand.NextDouble() - 1); } else { cp.Mass = body.Mass * Math.Pow(cp.Radius / origRadius, 3) * Math.Pow(2, 2.0 * rand.NextDouble() - 1); } /*foreach (Transform t in ScaledSpace.Instance.scaledSpaceTransforms) * { * if (t.gameObject.name == body.gameObject.name) * { * float origLocalScale = t.localScale.x; * float scaleFactor = (float)((double)origLocalScale * cp.Radius / origRadius); * t.localScale = new Vector3(scaleFactor, scaleFactor, scaleFactor); * } * }*/ cp.RotationPeriod = body.rotationPeriod; cp.SemiMajorAxis = body.orbit.semiMajorAxis; cp.Eccentricity = body.orbit.eccentricity; cp.Inclination = body.orbit.inclination; cp.MeanAnomalyAtEpoch = body.orbit.meanAnomalyAtEpoch; cp.LAN = body.orbit.LAN; cp.ArgumentOfPeriapsis = body.orbit.argumentOfPeriapsis; cp.ReferenceBody = null; tempPlanet.Add(cp); } } // sorting planets by mass tempPlanet.Sort(CompareByMass); int i = 0; foreach (ChangedPlanet cp in tempPlanet) { i++; cp.Rank = i; } int numberOfPlanets = i; print("number of planets = " + numberOfPlanets); // generating orbital parameters double smaSolarMin = 2000000000; // minimum solar orbit semi-major axis double smaSolarMax = 100000000000; // maximum solar orbit semi-major axis if (File.Exists(KSPUtil.ApplicationRootPath + "/GameData/RealSolarSystem/RealSolarSystem.cfg")) // checks for RSS { smaSolarMin = 10 * smaSolarMin; smaSolarMax = 30 * smaSolarMax; } if (File.Exists(KSPUtil.ApplicationRootPath + "/GameData/PlanetFactory/PlanetFactory.dll")) // checks for PlanetFactory { smaSolarMax = 5 * smaSolarMax; } // randomizing parameters double eccMax = 0.4; // maximum eccentricity double incMax = 20; // maximum inclination double smaMinRadius = 10.0; // minimum semi-major axis as multiplier of reference body radius double smaMaxSOI = 0.4; // maximum semi-major axis as multiplier of reference body SOI radius double maxMassRatio = 0.1; // maximum ratio between the masses of a satellite and its primary double minTidalLockingMassRatio = 0.02; // minimum ratio between the masses of a satellite and its primary before the primary is tidally locked to the satellite double maxTidalLockingRadius = 80; // maximum separation between a primary and its satellite at which the satellite is tidally locked double maxRotationRate = 0.2; // maximum rotation speed as a multiple of orbital speed at the surface double minRotationFactor = 0.01; // minimum rotation speed factor as a multiple of maximum rotation speed double eccIncExponent = 2.0; // controls how circular/equatorial large planet/moon orbits are double soiSeparationFactor = 2.0; // controls how far apart planets/moons are in terms of their SOI; double sunSeparationFactor = 0.1; // controls how far apart planets orbiting the Sun are in terms of their SMA; double sma = 0; double ecc = 0; int nSun = 5; // inverse of chance that a body orbits the Sun for (int j = 1; j <= i; j++) { foreach (ChangedPlanet cp in tempPlanet) { if (cp.Rank == j) { print("Changing " + cp.Name + "'s orbit, rank " + j + "."); // 1/nSun chance that the planet orbits the Sun int r1 = rand.Next(nSun); print("r1 = " + r1); if (r1 == 0) { cp.ReferenceBody = "Sun"; // excludes orbits that cross SOI with another body List <double> excludedRegionsLow = new List <double>(); List <double> excludedRegionsHigh = new List <double>(); foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.ReferenceBody == "Sun" && cp1.Rank < cp.Rank) { double cp1SOI = cp1.SemiMajorAxis * Math.Pow(cp1.Mass / sun.Mass, 0.4); excludedRegionsLow.Add(cp1.SemiMajorAxis * (1 - sunSeparationFactor) * (1 - cp1.Eccentricity) - 2 * cp1SOI * soiSeparationFactor); excludedRegionsHigh.Add(cp1.SemiMajorAxis * (1 + sunSeparationFactor) * (1 + cp1.Eccentricity) + 2 * cp1SOI * soiSeparationFactor); } } print("Finished excluded zones for " + cp.Name); bool orbitPermitted = false; while (!orbitPermitted) { orbitPermitted = true; sma = smaSolarMin + Math.Pow(rand.NextDouble(), 2) * (smaSolarMax - smaSolarMin); ecc = eccMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); // more massive planets have lower eccentricities print("Trying out SMA = " + sma); for (int k = 0; k < excludedRegionsLow.Count; k++) { if (sma * (1 + ecc) > excludedRegionsLow[k] && sma * (1 - ecc) < excludedRegionsHigh[k]) { orbitPermitted = false; } } } cp.SemiMajorAxis = sma; cp.Eccentricity = ecc; cp.Inclination = incMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); // more massive planets have lower inclinations cp.MeanAnomalyAtEpoch = 2 * Math.PI * rand.NextDouble(); cp.LAN = 360 * rand.NextDouble(); cp.ArgumentOfPeriapsis = 360 * rand.NextDouble(); print("Planet " + cp.Name + " is orbiting Sun1."); } // otherwise, chance of orbiting anything bigger than itself (including Sun) else { bool refBodyAllowed = false; int r2 = 0; while (!refBodyAllowed) { r2 = (int)(j - (j * Math.Pow(rand.NextDouble(), 3))); print("r2 = " + r2); if (r2 == 0) // orbiting Sun { refBodyAllowed = true; cp.ReferenceBody = "Sun"; // excludes orbits that cross SOI with another body List <double> excludedRegionsLow = new List <double>(); List <double> excludedRegionsHigh = new List <double>(); foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.ReferenceBody == "Sun" && cp1.Rank < cp.Rank) { print("Adding " + cp1.Name + " to excluded SOIs."); double cp1SOI = cp1.SemiMajorAxis * Math.Pow(cp1.Mass / sun.Mass, 0.4); excludedRegionsLow.Add(cp1.SemiMajorAxis * (1 - sunSeparationFactor) * (1 - cp1.Eccentricity) - 2 * cp1SOI * soiSeparationFactor); excludedRegionsHigh.Add(cp1.SemiMajorAxis * (1 + sunSeparationFactor) * (1 + cp1.Eccentricity) + 2 * cp1SOI * soiSeparationFactor); } } print("Finished excluded zones for " + cp.Name); bool orbitPermitted = false; int orbitTryCount = 0; while (!orbitPermitted && orbitTryCount <= 5) { orbitPermitted = true; sma = smaSolarMin + Math.Pow(rand.NextDouble(), 2) * (smaSolarMax - smaSolarMin); ecc = eccMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); print("Trying out SMA = " + sma); for (int k = 0; k < excludedRegionsLow.Count; k++) { print("k = " + k); if (sma * (1 + ecc) > excludedRegionsLow[k] && sma * (1 - ecc) < excludedRegionsHigh[k]) { orbitPermitted = false; print("orbit permitted = " + orbitPermitted); } } orbitTryCount++; print("orbitTryCount = " + orbitTryCount); if (orbitTryCount > 5) { refBodyAllowed = false; } } cp.SemiMajorAxis = sma; cp.Eccentricity = ecc; cp.Inclination = incMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); cp.MeanAnomalyAtEpoch = 2 * Math.PI * rand.NextDouble(); cp.LAN = 360 * rand.NextDouble(); cp.ArgumentOfPeriapsis = 360 * rand.NextDouble(); print("Planet " + cp.Name + " is orbiting Sun2."); } else // orbiting another body { refBodyAllowed = true; ChangedPlanet cpRef = tempPlanet.Find(cp2 => cp2.Rank == r2); cp.ReferenceBody = cpRef.Name; if (cp.Mass >= cpRef.Mass * maxMassRatio) { refBodyAllowed = false; } double cpRefSOI = 0; if (cpRef.ReferenceBody == "Sun") { cpRefSOI = cpRef.SemiMajorAxis * Math.Pow(cpRef.Mass / (sun.Mass + cpRef.Mass), 0.4); } else { foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.Name == cpRef.ReferenceBody && cp1.Rank < cpRef.Rank) { cpRefSOI = cpRef.SemiMajorAxis * Math.Pow(cpRef.Mass / (cp1.Mass + cpRef.Mass), 0.4); } } } double smaMin = cpRef.Radius * smaMinRadius + cp.Radius; double smaMax = cpRefSOI * smaMaxSOI; if (smaMin > smaMax) { refBodyAllowed = false; } // excludes orbits that cross SOI with another body List <double> excludedRegionsLow = new List <double>(); List <double> excludedRegionsHigh = new List <double>(); foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.ReferenceBody == cpRef.Name && cp1.Rank < cp.Rank) { double cp1SOI = cp1.SemiMajorAxis * Math.Pow(cp1.Mass / (cpRef.Mass + cp1.Mass), 0.4); excludedRegionsLow.Add(cp1.SemiMajorAxis * (1 - cp1.Eccentricity) - 2 * cp1SOI * soiSeparationFactor); excludedRegionsHigh.Add(cp1.SemiMajorAxis * (1 + cp1.Eccentricity) + 2 * cp1SOI * soiSeparationFactor); } } bool orbitPermitted = false; int orbitTryCount = 0; while (!orbitPermitted && orbitTryCount < 10) { orbitPermitted = true; sma = smaMin + Math.Pow(rand.NextDouble(), 4) * (smaMax - smaMin); ecc = eccMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); for (int k = 0; k < excludedRegionsLow.Count; k++) { if (sma * (1 + ecc) > excludedRegionsLow[k] && sma * (1 - ecc) < excludedRegionsHigh[k]) { orbitPermitted = false; } } orbitTryCount++; if (orbitTryCount >= 10) { refBodyAllowed = false; } } cp.SemiMajorAxis = sma; cp.Eccentricity = ecc; cp.Inclination = incMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); cp.MeanAnomalyAtEpoch = 2 * Math.PI * rand.NextDouble(); cp.LAN = 360 * rand.NextDouble(); cp.ArgumentOfPeriapsis = 360 * rand.NextDouble(); // changing rotation period if (sma <= cpRef.Radius * maxTidalLockingRadius) { // tidal locking of satellite to primary if close enough cp.RotationPeriod = 2 * Math.PI * Math.Sqrt((Math.Pow(sma, 3) / 6.674E-11) / (cp.Mass + cpRef.Mass)); if (cp.Mass >= cpRef.Mass * minTidalLockingMassRatio && sma <= cpRef.Radius * maxTidalLockingRadius / 3 && refBodyAllowed == true) { // tidal locking of primary to satellite if close enough and massive enough cpRef.RotationPeriod = 2 * Math.PI * Math.Sqrt((Math.Pow(sma, 3) / 6.674E-11) / (cp.Mass + cpRef.Mass)); } } else { // if no tidal locking, rotation speed is inversely distributed between maxRotationRate and maxRotationRate*minRotationFactor cp.RotationPeriod = (1 / maxRotationRate * 2 * Math.PI * Math.Sqrt((Math.Pow(cp.Radius, 3) / 6.674E-11) / cp.Mass)) / (minRotationFactor + (1 - minRotationFactor) * rand.NextDouble()); } print("Planet " + cp.Name + " is orbiting " + cpRef.Name + "."); } } print(cp.Name + " orbit changed."); } } } } List <ChangedPlanet> resultPlanet = new List <ChangedPlanet>(); foreach (ChangedPlanet cp in tempPlanet) { ChangedPlanet planet = new ChangedPlanet(); planet = cp; resultPlanet.Add(planet); } PlanetSettings.Instance.Planets = resultPlanet.ToArray(); PlanetSettings.Instance.Save(KSPUtil.ApplicationRootPath + "/saves/" + HighLogic.SaveFolder + "/PlanetRandomizer.cfg"); RebuildSystem(); /*if (HighLogic.LoadedScene == GameScenes.SPACECENTER) * { * PQSCity ksc = null; * foreach (PQSCity city in Resources.FindObjectsOfTypeAll(typeof(PQSCity))) * { * if (city.name == "KSC") * { * ksc = city; * break; * } * } * if (ksc == null) * { * return; * } * ksc.repositionToSphere = true; * foreach (SpaceCenterCamera2 cam in Resources.FindObjectsOfTypeAll(typeof(SpaceCenterCamera2))) * { * if (ksc.repositionToSphere || ksc.repositionToSphereSurface) * { * CelestialBody Kerbin = FlightGlobals.Bodies.Find(body => body.name == ksc.sphere.name); * if (Kerbin == null) * { * return; * } * double nomHeight = Kerbin.pqsController.GetSurfaceHeight((Vector3d)ksc.repositionRadial.normalized) - Kerbin.Radius; * if (ksc.repositionToSphereSurface) * { * nomHeight += ksc.repositionRadiusOffset; * } * cam.altitudeInitial = 0f - (float)nomHeight; * } * else * { * cam.altitudeInitial = 0f - (float)ksc.repositionRadiusOffset; * } * cam.ResetCamera(); * } * }*/ }
private void ChangeSystem() { print("Changing System"); System.Random rand = new System.Random(PlanetSettings.Instance.seed); CelestialBody sun = GetSun(); List<ChangedPlanet> tempPlanet = new List<ChangedPlanet>(); foreach (CelestialBody body in FlightGlobals.Bodies) { if (body.gameObject.name != "Sun") { ChangedPlanet cp = new ChangedPlanet(); cp.Name = body.gameObject.name; print("Changing " + cp.Name); double origRadius = body.Radius; if (body.name != "Kerbin" && body.pqsController != null) { cp.Radius = origRadius * Math.Pow(2, 2.0 * rand.NextDouble() - 1); } else { cp.Radius = origRadius; // Kerbin, gas giants, and stars don't change their radius } if (body.name == "Kerbin") { cp.Mass = body.Mass; // Kerbin doesn't change its mass } else if (body.Mass >= sun.Mass * 0.1) { cp.Mass = sun.Mass * 0.1 * Math.Pow(2, 2.0 * rand.NextDouble() - 1); } else { cp.Mass = body.Mass * Math.Pow(cp.Radius / origRadius, 3) * Math.Pow(2, 2.0 * rand.NextDouble() - 1); } /*foreach (Transform t in ScaledSpace.Instance.scaledSpaceTransforms) { if (t.gameObject.name == body.gameObject.name) { float origLocalScale = t.localScale.x; float scaleFactor = (float)((double)origLocalScale * cp.Radius / origRadius); t.localScale = new Vector3(scaleFactor, scaleFactor, scaleFactor); } }*/ cp.RotationPeriod = body.rotationPeriod; cp.SemiMajorAxis = body.orbit.semiMajorAxis; cp.Eccentricity = body.orbit.eccentricity; cp.Inclination = body.orbit.inclination; cp.MeanAnomalyAtEpoch = body.orbit.meanAnomalyAtEpoch; cp.LAN = body.orbit.LAN; cp.ArgumentOfPeriapsis = body.orbit.argumentOfPeriapsis; cp.ReferenceBody = null; tempPlanet.Add(cp); } } // sorting planets by mass tempPlanet.Sort(CompareByMass); int i = 0; foreach (ChangedPlanet cp in tempPlanet) { i++; cp.Rank = i; } int numberOfPlanets = i; print("number of planets = " + numberOfPlanets); // generating orbital parameters double smaSolarMin = 2000000000; // minimum solar orbit semi-major axis double smaSolarMax = 100000000000; // maximum solar orbit semi-major axis if (File.Exists(KSPUtil.ApplicationRootPath + "/GameData/RealSolarSystem/RealSolarSystem.cfg")) // checks for RSS { smaSolarMin = 10 * smaSolarMin; smaSolarMax = 30 * smaSolarMax; } if (File.Exists(KSPUtil.ApplicationRootPath + "/GameData/PlanetFactory/PlanetFactory.dll")) // checks for PlanetFactory { smaSolarMax = 5 * smaSolarMax; } // randomizing parameters double eccMax = 0.4; // maximum eccentricity double incMax = 20; // maximum inclination double smaMinRadius = 10.0; // minimum semi-major axis as multiplier of reference body radius double smaMaxSOI = 0.4; // maximum semi-major axis as multiplier of reference body SOI radius double maxMassRatio = 0.1; // maximum ratio between the masses of a satellite and its primary double minTidalLockingMassRatio = 0.02; // minimum ratio between the masses of a satellite and its primary before the primary is tidally locked to the satellite double maxTidalLockingRadius = 80; // maximum separation between a primary and its satellite at which the satellite is tidally locked double maxRotationRate = 0.2; // maximum rotation speed as a multiple of orbital speed at the surface double minRotationFactor = 0.01; // minimum rotation speed factor as a multiple of maximum rotation speed double eccIncExponent = 2.0; // controls how circular/equatorial large planet/moon orbits are double soiSeparationFactor = 2.0; // controls how far apart planets/moons are in terms of their SOI; double sunSeparationFactor = 0.1; // controls how far apart planets orbiting the Sun are in terms of their SMA; double sma = 0; double ecc = 0; int nSun = 5; // inverse of chance that a body orbits the Sun for (int j = 1; j <= i; j++) { foreach (ChangedPlanet cp in tempPlanet) { if (cp.Rank == j) { print("Changing " + cp.Name + "'s orbit, rank " + j + "."); // 1/nSun chance that the planet orbits the Sun int r1 = rand.Next(nSun); print("r1 = " + r1); if (r1 == 0) { cp.ReferenceBody = "Sun"; // excludes orbits that cross SOI with another body List<double> excludedRegionsLow = new List<double>(); List<double> excludedRegionsHigh = new List<double>(); foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.ReferenceBody == "Sun" && cp1.Rank < cp.Rank) { double cp1SOI = cp1.SemiMajorAxis * Math.Pow(cp1.Mass / sun.Mass, 0.4); excludedRegionsLow.Add(cp1.SemiMajorAxis * (1 - sunSeparationFactor) * (1 - cp1.Eccentricity) - 2 * cp1SOI * soiSeparationFactor); excludedRegionsHigh.Add(cp1.SemiMajorAxis * (1 + sunSeparationFactor) * (1 + cp1.Eccentricity) + 2 * cp1SOI * soiSeparationFactor); } } print("Finished excluded zones for " + cp.Name); bool orbitPermitted = false; while (!orbitPermitted) { orbitPermitted = true; sma = smaSolarMin + Math.Pow(rand.NextDouble(), 2) * (smaSolarMax - smaSolarMin); ecc = eccMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); // more massive planets have lower eccentricities print("Trying out SMA = " + sma); for (int k = 0; k < excludedRegionsLow.Count; k++) { if (sma * (1 + ecc) > excludedRegionsLow[k] && sma * (1 - ecc) < excludedRegionsHigh[k]) { orbitPermitted = false; } } } cp.SemiMajorAxis = sma; cp.Eccentricity = ecc; cp.Inclination = incMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); // more massive planets have lower inclinations cp.MeanAnomalyAtEpoch = 2 * Math.PI * rand.NextDouble(); cp.LAN = 360 * rand.NextDouble(); cp.ArgumentOfPeriapsis = 360 * rand.NextDouble(); print("Planet " + cp.Name + " is orbiting Sun1."); } // otherwise, chance of orbiting anything bigger than itself (including Sun) else { bool refBodyAllowed = false; int r2 = 0; while (!refBodyAllowed) { r2 = (int)(j - (j * Math.Pow(rand.NextDouble(), 3))); print("r2 = " + r2); if (r2 == 0) // orbiting Sun { refBodyAllowed = true; cp.ReferenceBody = "Sun"; // excludes orbits that cross SOI with another body List<double> excludedRegionsLow = new List<double>(); List<double> excludedRegionsHigh = new List<double>(); foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.ReferenceBody == "Sun" && cp1.Rank < cp.Rank) { print("Adding " + cp1.Name + " to excluded SOIs."); double cp1SOI = cp1.SemiMajorAxis * Math.Pow(cp1.Mass / sun.Mass, 0.4); excludedRegionsLow.Add(cp1.SemiMajorAxis * (1 - sunSeparationFactor) * (1 - cp1.Eccentricity) - 2 * cp1SOI * soiSeparationFactor); excludedRegionsHigh.Add(cp1.SemiMajorAxis * (1 + sunSeparationFactor) * (1 + cp1.Eccentricity) + 2 * cp1SOI * soiSeparationFactor); } } print("Finished excluded zones for " + cp.Name); bool orbitPermitted = false; int orbitTryCount = 0; while (!orbitPermitted && orbitTryCount <= 5) { orbitPermitted = true; sma = smaSolarMin + Math.Pow(rand.NextDouble(), 2) * (smaSolarMax - smaSolarMin); ecc = eccMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); print("Trying out SMA = " + sma); for (int k = 0; k < excludedRegionsLow.Count; k++) { print("k = " + k); if (sma * (1 + ecc) > excludedRegionsLow[k] && sma * (1 - ecc) < excludedRegionsHigh[k]) { orbitPermitted = false; print("orbit permitted = " + orbitPermitted); } } orbitTryCount++; print("orbitTryCount = " + orbitTryCount); if (orbitTryCount > 5) { refBodyAllowed = false; } } cp.SemiMajorAxis = sma; cp.Eccentricity = ecc; cp.Inclination = incMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); cp.MeanAnomalyAtEpoch = 2 * Math.PI * rand.NextDouble(); cp.LAN = 360 * rand.NextDouble(); cp.ArgumentOfPeriapsis = 360 * rand.NextDouble(); print("Planet " + cp.Name + " is orbiting Sun2."); } else // orbiting another body { refBodyAllowed = true; ChangedPlanet cpRef = tempPlanet.Find(cp2 => cp2.Rank == r2); cp.ReferenceBody = cpRef.Name; if (cp.Mass >= cpRef.Mass * maxMassRatio) { refBodyAllowed = false; } double cpRefSOI = 0; if (cpRef.ReferenceBody == "Sun") { cpRefSOI = cpRef.SemiMajorAxis * Math.Pow(cpRef.Mass / (sun.Mass + cpRef.Mass), 0.4); } else { foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.Name == cpRef.ReferenceBody && cp1.Rank < cpRef.Rank) { cpRefSOI = cpRef.SemiMajorAxis * Math.Pow(cpRef.Mass / (cp1.Mass + cpRef.Mass), 0.4); } } } double smaMin = cpRef.Radius * smaMinRadius + cp.Radius; double smaMax = cpRefSOI * smaMaxSOI; if (smaMin > smaMax) { refBodyAllowed = false; } // excludes orbits that cross SOI with another body List<double> excludedRegionsLow = new List<double>(); List<double> excludedRegionsHigh = new List<double>(); foreach (ChangedPlanet cp1 in tempPlanet) { if (cp1.ReferenceBody == cpRef.Name && cp1.Rank < cp.Rank) { double cp1SOI = cp1.SemiMajorAxis * Math.Pow(cp1.Mass / (cpRef.Mass + cp1.Mass), 0.4); excludedRegionsLow.Add(cp1.SemiMajorAxis * (1 - cp1.Eccentricity) - 2 * cp1SOI * soiSeparationFactor); excludedRegionsHigh.Add(cp1.SemiMajorAxis * (1 + cp1.Eccentricity) + 2 * cp1SOI * soiSeparationFactor); } } bool orbitPermitted = false; int orbitTryCount = 0; while (!orbitPermitted && orbitTryCount < 10) { orbitPermitted = true; sma = smaMin + Math.Pow(rand.NextDouble(), 4) * (smaMax - smaMin); ecc = eccMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); for (int k = 0; k < excludedRegionsLow.Count; k++) { if (sma * (1 + ecc) > excludedRegionsLow[k] && sma * (1 - ecc) < excludedRegionsHigh[k]) { orbitPermitted = false; } } orbitTryCount++; if (orbitTryCount >= 10) { refBodyAllowed = false; } } cp.SemiMajorAxis = sma; cp.Eccentricity = ecc; cp.Inclination = incMax * rand.NextDouble() * Math.Pow((double)cp.Rank / numberOfPlanets, eccIncExponent); cp.MeanAnomalyAtEpoch = 2 * Math.PI * rand.NextDouble(); cp.LAN = 360 * rand.NextDouble(); cp.ArgumentOfPeriapsis = 360 * rand.NextDouble(); // changing rotation period if (sma <= cpRef.Radius * maxTidalLockingRadius) { // tidal locking of satellite to primary if close enough cp.RotationPeriod = 2 * Math.PI * Math.Sqrt((Math.Pow(sma, 3) / 6.674E-11) / (cp.Mass + cpRef.Mass)); if (cp.Mass >= cpRef.Mass * minTidalLockingMassRatio && sma <= cpRef.Radius * maxTidalLockingRadius / 3 && refBodyAllowed == true) { // tidal locking of primary to satellite if close enough and massive enough cpRef.RotationPeriod = 2 * Math.PI * Math.Sqrt((Math.Pow(sma, 3) / 6.674E-11) / (cp.Mass + cpRef.Mass)); } } else { // if no tidal locking, rotation speed is inversely distributed between maxRotationRate and maxRotationRate*minRotationFactor cp.RotationPeriod = (1 / maxRotationRate * 2 * Math.PI * Math.Sqrt((Math.Pow(cp.Radius, 3) / 6.674E-11) / cp.Mass)) / (minRotationFactor + (1 - minRotationFactor) * rand.NextDouble()); } print("Planet " + cp.Name + " is orbiting " + cpRef.Name + "."); } } print(cp.Name + " orbit changed."); } } } } List<ChangedPlanet> resultPlanet = new List<ChangedPlanet>(); foreach (ChangedPlanet cp in tempPlanet) { ChangedPlanet planet = new ChangedPlanet(); planet = cp; resultPlanet.Add(planet); } PlanetSettings.Instance.Planets = resultPlanet.ToArray(); PlanetSettings.Instance.Save(KSPUtil.ApplicationRootPath + "/saves/" + HighLogic.SaveFolder + "/PlanetRandomizer.cfg"); RebuildSystem(); /*if (HighLogic.LoadedScene == GameScenes.SPACECENTER) { PQSCity ksc = null; foreach (PQSCity city in Resources.FindObjectsOfTypeAll(typeof(PQSCity))) { if (city.name == "KSC") { ksc = city; break; } } if (ksc == null) { return; } ksc.repositionToSphere = true; foreach (SpaceCenterCamera2 cam in Resources.FindObjectsOfTypeAll(typeof(SpaceCenterCamera2))) { if (ksc.repositionToSphere || ksc.repositionToSphereSurface) { CelestialBody Kerbin = FlightGlobals.Bodies.Find(body => body.name == ksc.sphere.name); if (Kerbin == null) { return; } double nomHeight = Kerbin.pqsController.GetSurfaceHeight((Vector3d)ksc.repositionRadial.normalized) - Kerbin.Radius; if (ksc.repositionToSphereSurface) { nomHeight += ksc.repositionRadiusOffset; } cam.altitudeInitial = 0f - (float)nomHeight; } else { cam.altitudeInitial = 0f - (float)ksc.repositionRadiusOffset; } cam.ResetCamera(); } }*/ }
private static int CompareByMass(ChangedPlanet a, ChangedPlanet b) { if (a == null) { if (b == null) return 0; else return -1; } else { if (b == null) return 1; else return b.Mass.CompareTo(a.Mass); } }
public void DefaultSystem() { if (!File.Exists(KSPUtil.ApplicationRootPath + "/GameData/PlanetRandomizer/Resources/PlanetRandomizerDefault.cfg")) { print("Saving default system"); List<ChangedPlanet> tempPlanet = new List<ChangedPlanet>(); foreach (CelestialBody body in FlightGlobals.Bodies) { if (body.gameObject.name != "Sun") { ChangedPlanet cp = new ChangedPlanet(); cp.Name = body.gameObject.name; cp.Radius = body.Radius; cp.Mass = body.Mass; cp.RotationPeriod = body.rotationPeriod; cp.SemiMajorAxis = body.orbit.semiMajorAxis; cp.Eccentricity = body.orbit.eccentricity; cp.Inclination = body.orbit.inclination; cp.MeanAnomalyAtEpoch = body.orbit.meanAnomalyAtEpoch; cp.LAN = body.orbit.LAN; cp.ArgumentOfPeriapsis = body.orbit.argumentOfPeriapsis; cp.ReferenceBody = body.orbit.referenceBody.name; tempPlanet.Add(cp); } } PlanetDefault.Instance.Planets = tempPlanet.ToArray(); PlanetDefault.Instance.Save(KSPUtil.ApplicationRootPath + "/GameData/PlanetRandomizer/Resources/PlanetRandomizerDefault.cfg"); RebuildSystemDef(); } else { PlanetDefault.Load(KSPUtil.ApplicationRootPath + "/GameData/PlanetRandomizer/Resources/PlanetRandomizerDefault.cfg"); RebuildSystemDef(); } }