private void ComputeLong(EdgePlacerSystem.AnnotatedNode first, EdgePlacerSystem.AnnotatedNode last, LongPlanData data) { var lenPerCount = data.Length / data.Count; _vertices.Clear(); _vertices.Add(first); var time = 0f; var prev = data.Curve.Sample(0); var lengthElapsed = 0d; const float timeStep = .001f; for (var i = 1; i < data.Count; i++) { while (lengthElapsed < lenPerCount * i) { time += timeStep; var curr = data.Curve.Sample(time); lengthElapsed += Vector3D.Distance(prev, curr); prev = curr; } _vertices.Add(CreateVertex(prev)); } _vertices.Add(last); }
protected override bool Start(MyHandItemActionEnum action) { if (!IsLocallyControlled) { return(false); } var player = MyAPIGateway.Players.GetPlayerControllingEntity(Holder); if (player == null) { return(false); } if (Target.Entity == null || Vector3D.DistanceSquared(Target.Position, Holder.GetPosition()) > ClickDistSq) { player.ShowNotification($"Too far away from the chosen point. Click closer to yourself.", 2000, null, new Vector4(1, 0, 0, 1)); return(false); } switch (action) { case MyHandItemActionEnum.Tertiary: return(_vertices.Count > 0); case MyHandItemActionEnum.Secondary: string err; if (ValidateDeconstruct(out err, true)) { return(true); } if (!string.IsNullOrEmpty(err)) { player.ShowNotification(err, 2000, null, new Vector4(1, 0, 0, 1)); } if (_vertices.Count > 0 && Vector3D.DistanceSquared(_vertices[_vertices.Count - 1].Position, Target.Position) < 1) { _vertices.RemoveAt(_vertices.Count - 1); } return(false); case MyHandItemActionEnum.Primary: if (_vertices.Count == 1 && MyAPIGateway.Input.IsKeyDown(MyKeys.Shift)) { var originalStart = _vertices[0]; var lastVertex = CreateVertex(Target.Position); _vertices.Add(lastVertex); EdgePlacerSystem.AnnotateNodes(Graph, _vertices); var curveData = new LongPlanData(this, _vertices[0], _vertices[1]); var jointData = EdgePlacerSystem.ComputeEdgeParameters(_vertices[0], _vertices[_vertices.Count - 1]); { _tmpMessages.Clear(); if (jointData.BendRadians.HasValue) { var angle = jointData.BendRadians.Value / curveData.Count; if (angle > RailConstants.LongToleranceFactor * PlacedDefinition.MaxAngleRadians) { _tmpMessages.Add( $"Too curvy {angle * 180 / Math.PI:F0}º >= {RailConstants.LongToleranceFactor * PlacedDefinition.MaxAngleDegrees:F0}º"); } } // ReSharper disable once InvertIf if (jointData.Grade.HasValue) { var grade = jointData.Grade.Value; // ReSharper disable once InvertIf if (Math.Abs(grade) > RailConstants.LongToleranceFactor * PlacedDefinition.MaxGradeRatio) { _tmpMessages.Add( $"Too steep {grade * 100:F0}% {(grade < 0 ? "<= -" : ">= ")}{RailConstants.LongToleranceFactor * PlacedDefinition.MaxGradeRatio * 100:F0}%"); } } if (_tmpMessages.Count > 0) { player.ShowNotification(string.Join("\n", _tmpMessages), 2000, null, new Vector4(1, 0, 0, 1)); _tmpMessages.Clear(); _vertices.Clear(); _vertices.Add(originalStart); return(false); } } ComputeLong(_vertices[0], _vertices[1], curveData); _vertices.RemoveAt(_vertices.Count - 1); _tmpMessages.Clear(); player.ShowNotification($"Dividing into {curveData.Count} segments"); if (!ValidatePlace(_tmpMessages, true)) { player.ShowNotification(string.Join("\n", _tmpMessages), 2000, null, new Vector4(1, 0, 0, 1)); _vertices.Clear(); _vertices.Add(originalStart); return(false); } return(false); } _tmpMessages.Clear(); if (ValidatePlace(_tmpMessages, true)) { return(true); } if (_tmpMessages.Count > 0) { player.ShowNotification(string.Join("\n", _tmpMessages), 2000, null, new Vector4(1, 0, 0, 1)); } _tmpMessages.Clear(); return(false); case MyHandItemActionEnum.None: default: return(false); } }