private void positionNode() { //position node float width = nodePlacard.rectTransform.rect.width * nodePlacard.transform.localScale.x; float height = nodePlacard.rectTransform.rect.height * nodePlacard.transform.localScale.y; double trueAnomaly = MiscHelperFuncs.AngleBetweenVector2(shipElements.Eccentricity, node.getNodePosition()); if (trueAnomaly > Math.PI) { trueAnomaly -= 2 * Math.PI; } bool towardsPerigeeOrbit; if (trueAnomaly < 0) { if (shipElements.Clockwise) { towardsPerigeeOrbit = false; } else { towardsPerigeeOrbit = true; } } else { if (shipElements.Clockwise) { towardsPerigeeOrbit = true; } else { towardsPerigeeOrbit = false; } } double velocityAngle = OrbitalHelper.calculateVelocityAngle(node.getNodePosition(), shipElements.Eccentricity, shipElements.SemiMajorAxis, trueAnomaly, shipElements.GlobalRotationAngle, shipElements.Clockwise, towardsPerigeeOrbit, shipElements.OrbitType); Vector2 offsetVector; if (shipElements.Clockwise) { offsetVector = OrbitalHelper.assembleVelocityVector(velocityAngle + Math.PI / 2, 1).normalized * Mathf.Sqrt(Mathf.Pow(width / 2, 2) + Mathf.Pow(height / 2, 2)); } else { offsetVector = OrbitalHelper.assembleVelocityVector(velocityAngle - Math.PI / 2, 1).normalized * Mathf.Sqrt(Mathf.Pow(width / 2, 2) + Mathf.Pow(height / 2, 2)); } nodeButton.transform.position = node.getNodePosition() + offsetVector + shipElements.GlobalTransformationVector; nodeButton.transform.localScale = new Vector3(GlobalElements.zoomLevel / GlobalElements.UI_SCALE_CONST, GlobalElements.zoomLevel / GlobalElements.UI_SCALE_CONST, 0); nodePlacard.transform.position = node.getNodePosition() + offsetVector + shipElements.GlobalTransformationVector; nodePlacard.transform.localScale = new Vector3(GlobalElements.zoomLevel / GlobalElements.UI_SCALE_CONST, GlobalElements.zoomLevel / GlobalElements.UI_SCALE_CONST, 0); nodePlacard.transform.rotation = Quaternion.AngleAxis(Mathf.Atan2(offsetVector.y, offsetVector.x) * Mathf.Rad2Deg - 45, Vector3.forward); thrustVectorHandle.transform.position = node.getNodePosition() + shipElements.GlobalTransformationVector + thrustVector; thrustVectorHandle.transform.localScale = new Vector3(GlobalElements.zoomLevel / GlobalElements.UI_SCALE_CONST / 2, GlobalElements.zoomLevel / GlobalElements.UI_SCALE_CONST / 2, 0); lineDrawer.DrawLine(node.getNodePosition() + shipElements.GlobalTransformationVector, node.getNodePosition() + shipElements.GlobalTransformationVector + thrustVector, Color.red); }
//Takes in the ships current gravity elements according to its last encounter, current massive body elements as they are at tiem 0 and current massivebodyelements as they are at time 0 private void predictAnEncounter(Encounter currentEncounter, ref List <Encounter> encounters) { encounters.Add(currentEncounter); //data sources MassiveBodyElements currentMassiveBody = currentEncounter.GravElements.massiveBody.GetComponent <MassiveBodyElements>(); GravityElementsClass currentMassiveBodyGravElements = currentEncounter.GravElements.massiveBody.GetComponent <GravityElements>().getClassVersion(); iterations++; double time = 0; double currentOrbitalPeriod = calculatePeriod(currentEncounter.GravElements.OrbitType, currentEncounter.GravElements.SemiMajorAxis, currentEncounter.GravElements.Mu); bool foundNewEncounter = false; GameObject encounteredMassiveBody = null; while (time < currentOrbitalPeriod && !foundNewEncounter) { time += 0.01; //have we exited the current soi? double altitude = currentEncounter.GravElements.calculateLocalPositionAtFutureTime(time).magnitude; //the ships massive body is always at time 0 if (currentMassiveBody.SphereOfInfluence < altitude) { foundNewEncounter = true; encounteredMassiveBody = currentEncounter.GravElements.massiveBody.GetComponent <GravityElements>().massiveBody; break; } //have we entered a new soi? foreach (GameObject satelite in currentMassiveBody.satelites) { double sateliteSphereOfInfluence = satelite.GetComponent <MassiveBodyElements>().SphereOfInfluence; Vector2 sateliteLocalPosition = satelite.GetComponent <GravityElements>().calculateLocalPositionAtFutureTime(time + currentEncounter.TimeOfEncounter); Vector2 shipsLocalPosition = currentEncounter.GravElements.calculateLocalPositionAtFutureTime(time); if (Vector2.Distance(shipsLocalPosition, sateliteLocalPosition) < sateliteSphereOfInfluence) { foundNewEncounter = true; encounteredMassiveBody = satelite; break; } } if (time > 100) //hyperbolic orbit with infinite periode, this prevents infinite loops { break; } } //We have encountered nothing, just a regular eliptical orbit, or a hyperbolic one that's really long if (encounteredMassiveBody == null) { return; } //We have encountered a massive body, time to assemble a new encounter Tuple <Vector2, Vector2> returnInfo; returnInfo = currentEncounter.GravElements.calculateLocalPositionAndVelocityAtFutureTime(time); Vector2 shipPredictedLocalPosition = returnInfo.item1; Vector2 shipPredictedLocalVelocity = returnInfo.item2; returnInfo = currentMassiveBodyGravElements.calculateGlobalPositionAndVelocityAtFutureTime(time + currentEncounter.TimeOfEncounter); Vector2 currentMassiveBodyPredictedGlobalPosition = returnInfo.item1; Vector2 currentMassiveBodyPredictedGlobalVelocity = returnInfo.item2; returnInfo = encounteredMassiveBody.GetComponent <GravityElements>().calculateGlobalPositionAndVelocityAtFutureTime(time + currentEncounter.TimeOfEncounter); Vector2 encounteredMassiveBodyPredictedGlobalPosition = returnInfo.item1; Vector2 encounteredmassiveBodyPredictedGlobalVelocity = returnInfo.item2; Vector2 shipPositionRelativeToEncounter = (shipPredictedLocalPosition + currentMassiveBodyPredictedGlobalPosition) - encounteredMassiveBodyPredictedGlobalPosition; Vector2 shipVelocityRelativeToEncounter = (shipPredictedLocalVelocity + currentMassiveBodyPredictedGlobalVelocity) - encounteredmassiveBodyPredictedGlobalVelocity; GravityElementsClass newShipsGravityElements = calculateInitialOrbitalElements(shipPositionRelativeToEncounter, shipVelocityRelativeToEncounter, encounteredMassiveBody); //massive body is inputed in its state at time 0 //Change the ending true anomaly of the last encounter double startingTrueAnomaly = newShipsGravityElements.TrueAnomaly; double endingTrueAnomaly = MiscHelperFuncs.AngleBetweenVector2(currentEncounter.GravElements.Eccentricity, shipPredictedLocalPosition); encounters[encounters.Count - 1].EndingTrueAnomaly = endingTrueAnomaly; if (iterations < MAX_ITERATIONS) { GameObject tempPerigeeIcon = Instantiate(perigeeIcon); OrbitalPOI perigeePOI = new OrbitalPOI(tempPerigeeIcon, newShipsGravityElements.Perigee); Encounter newEncounter = new Encounter(newShipsGravityElements, startingTrueAnomaly, double.PositiveInfinity, time + currentEncounter.TimeOfEncounter, perigeePOI); predictAnEncounter(newEncounter, ref encounters); } }