Пример #1
0
        private static TrajectoryPoint[] Calculate(double bc, DragTableId id)
        {
            var dragTable = new MyDrag();

            var ammo = new Ammunition(
                weight: new Measurement <WeightUnit>(168, WeightUnit.Grain),
                ballisticCoefficient: new BallisticCoefficient(bc, id),
                muzzleVelocity: new Measurement <VelocityUnit>(555, VelocityUnit.MetersPerSecond),
                bulletDiameter: new Measurement <DistanceUnit>(0.224, DistanceUnit.Inch),
                bulletLength: new Measurement <DistanceUnit>(0.9, DistanceUnit.Inch));

            //define ACOG scope
            var sight = new Sight(
                sightHeight: new Measurement <DistanceUnit>(3.5, DistanceUnit.Inch),
                verticalClick: new Measurement <AngularUnit>(1.0 / 3.0, AngularUnit.InchesPer100Yards),
                horizontalClick: new Measurement <AngularUnit>(1.0 / 3.0, AngularUnit.InchesPer100Yards)
                );

            //M16 rifling
            var rifling = new Rifling(
                riflingStep: new Measurement <DistanceUnit>(12, DistanceUnit.Inch),
                direction: TwistDirection.Right);

            //standard 100 yard ACOG zeroing
            var zero = new ZeroingParameters(
                distance: new Measurement <DistanceUnit>(50, DistanceUnit.Yard),
                ammunition: null,
                atmosphere: null
                );

            //define rifle by sight, zeroing and rifling parameters
            var rifle = new Rifle(sight: sight, zero: zero, rifling: rifling);

            //define atmosphere
            var atmosphere = new Atmosphere(
                altitude: new Measurement <DistanceUnit>(0, DistanceUnit.Foot),
                pressure: new Measurement <PressureUnit>(29.92, PressureUnit.InchesOfMercury),
                pressureAtSeaLevel: false,
                temperature: new Measurement <TemperatureUnit>(59, TemperatureUnit.Fahrenheit),
                humidity: 0.78);

            var calc = new TrajectoryCalculator();

            //shot parameters
            var shot = new ShotParameters()
            {
                MaximumDistance = new Measurement <DistanceUnit>(2000, DistanceUnit.Meter),
                Step            = new Measurement <DistanceUnit>(100, DistanceUnit.Meter),
                //calculate sight angle for the specified zero distance
                SightAngle = calc.SightAngle(ammo, rifle, atmosphere, id == DragTableId.GC ? dragTable : null)
            };

            //calculate trajectory
            return(calc.Calculate(ammo, rifle, atmosphere, shot, null, id == DragTableId.GC ? dragTable : null));
        }
Пример #2
0
        public void CustomTable()
        {
            TableLoader  template = TableLoader.FromResource("g1_nowind");
            const double velocityAccuracyInPercent = 0.005, dropAccuracyInMOA = 0.2, windageAccuracyInMOA = 0.2;

            var table = DragTable.Get(template.Ammunition.BallisticCoefficient.Table);

            template.Ammunition.BallisticCoefficient = new BallisticCoefficient(template.Ammunition.BallisticCoefficient.Value, DragTableId.GC);


            var cal = new TrajectoryCalculator();

            ShotParameters shot = new ShotParameters()
            {
                Step            = new Measurement <DistanceUnit>(50, DistanceUnit.Yard),
                MaximumDistance = new Measurement <DistanceUnit>(1000, DistanceUnit.Yard),
                SightAngle      = cal.SightAngle(template.Ammunition, template.Rifle, template.Atmosphere, table),
                ShotAngle       = template.ShotParameters?.ShotAngle,
                CantAngle       = template.ShotParameters?.CantAngle,
            };

            var trajectory = cal.Calculate(template.Ammunition, template.Rifle, template.Atmosphere, shot, null, table);

            trajectory.Length.Should().Be(template.Trajectory.Count);

            for (int i = 0; i < trajectory.Length; i++)
            {
                var point         = trajectory[i];
                var templatePoint = template.Trajectory[i];

                point.Distance.In(templatePoint.Distance.Unit).Should().BeApproximately(templatePoint.Distance.Value, templatePoint.Distance.Value * velocityAccuracyInPercent, $"@{point.Distance:N0}");
                point.Velocity.In(templatePoint.Velocity.Unit).Should().BeApproximately(templatePoint.Velocity.Value, templatePoint.Velocity.Value * velocityAccuracyInPercent, $"@{point.Distance:N0}");

                var dropAccuracyInInch = Measurement <AngularUnit> .Convert(dropAccuracyInMOA, AngularUnit.MOA, AngularUnit.InchesPer100Yards) * templatePoint.Distance.In(DistanceUnit.Yard) / 100;

                var windageAccuracyInInch = Measurement <AngularUnit> .Convert(windageAccuracyInMOA, AngularUnit.MOA, AngularUnit.InchesPer100Yards) * templatePoint.Distance.In(DistanceUnit.Yard) / 100;

                point.Drop.In(DistanceUnit.Inch).Should().BeApproximately(templatePoint.Drop.In(DistanceUnit.Inch), dropAccuracyInInch, $"@{point.Distance:N0}");
                point.Windage.In(DistanceUnit.Inch).Should().BeApproximately(templatePoint.Windage.In(DistanceUnit.Inch), windageAccuracyInInch, $"@{point.Distance:N0}");
            }
        }
Пример #3
0
        public void Custom2()
        {
            var template = TableLoader.FromResource("custom2");

            using var stream = typeof(TrajectoryCalculatorTest).Assembly.GetManifestResourceStream($"BallisticCalculator.Test.resources.drg2.txt");
            var table = DrgDragTable.Open(stream);

            const double velocityAccuracyInPercent = 0.015, dropAccuracyInMOA = 0.25;

            var cal = new TrajectoryCalculator();

            ShotParameters shot = new ShotParameters()
            {
                Step            = new Measurement <DistanceUnit>(100, DistanceUnit.Meter),
                MaximumDistance = new Measurement <DistanceUnit>(1500, DistanceUnit.Meter),
                SightAngle      = cal.SightAngle(template.Ammunition, template.Rifle, template.Atmosphere, table),
                ShotAngle       = template.ShotParameters?.ShotAngle,
                CantAngle       = template.ShotParameters?.CantAngle,
            };

            var winds = template.Wind == null ? null : new Wind[] { template.Wind };

            var trajectory = cal.Calculate(template.Ammunition, template.Rifle, template.Atmosphere, shot, winds, table);

            trajectory.Length.Should().Be(template.Trajectory.Count);

            for (int i = 0; i < trajectory.Length; i++)
            {
                var point         = trajectory[i];
                var templatePoint = template.Trajectory[i];

                point.Distance.In(templatePoint.Distance.Unit).Should().BeApproximately(templatePoint.Distance.Value, templatePoint.Distance.Value * velocityAccuracyInPercent, $"@{point.Distance:N0}");
                point.Velocity.In(templatePoint.Velocity.Unit).Should().BeApproximately(templatePoint.Velocity.Value, templatePoint.Velocity.Value * velocityAccuracyInPercent, $"@{point.Distance:N0}");
                if (i > 0)
                {
                    var dropAccuracyInInch = Measurement <AngularUnit> .Convert(dropAccuracyInMOA, AngularUnit.MOA, AngularUnit.InchesPer100Yards) * templatePoint.Distance.In(DistanceUnit.Yard) / 100;

                    point.Drop.In(DistanceUnit.Inch).Should().BeApproximately(templatePoint.Drop.In(DistanceUnit.Inch), dropAccuracyInInch, $"@{point.Distance:N0}");
                }
            }
        }
Пример #4
0
        public void CustomTableNotSpecifiedException()
        {
            TableLoader template = TableLoader.FromResource("g1_nowind");

            template.Ammunition.BallisticCoefficient = new BallisticCoefficient(template.Ammunition.BallisticCoefficient.Value, DragTableId.GC);

            var cal = new TrajectoryCalculator();

            ((Action)(() => cal.SightAngle(template.Ammunition, template.Rifle, template.Atmosphere)))
            .Should().Throw <ArgumentNullException>();

            ShotParameters shot = new ShotParameters()
            {
                Step            = new Measurement <DistanceUnit>(50, DistanceUnit.Yard),
                MaximumDistance = new Measurement <DistanceUnit>(1000, DistanceUnit.Yard),
                SightAngle      = new Measurement <AngularUnit>(10, AngularUnit.MOA),
                ShotAngle       = template.ShotParameters?.ShotAngle,
                CantAngle       = template.ShotParameters?.CantAngle,
            };

            ((Action)(() => cal.Calculate(template.Ammunition, template.Rifle, template.Atmosphere, shot, null)))
            .Should().Throw <ArgumentNullException>();
        }
Пример #5
0
        public void TrajectoryTest(string name, double velocityAccuracyInPercent, double dropAccuracyInMOA, double windageAccuracyInMOA)
        {
            TableLoader template = TableLoader.FromResource(name);

            var cal = new TrajectoryCalculator();

            ShotParameters shot = new ShotParameters()
            {
                Step            = new Measurement <DistanceUnit>(50, DistanceUnit.Yard),
                MaximumDistance = new Measurement <DistanceUnit>(1000, DistanceUnit.Yard),
                SightAngle      = cal.SightAngle(template.Ammunition, template.Rifle, template.Atmosphere),
                ShotAngle       = template.ShotParameters?.ShotAngle,
                CantAngle       = template.ShotParameters?.CantAngle,
            };

            var winds = template.Wind == null ? null : new Wind[] { template.Wind };

            var trajectory = cal.Calculate(template.Ammunition, template.Rifle, template.Atmosphere, shot, winds);

            trajectory.Length.Should().Be(template.Trajectory.Count);

            for (int i = 0; i < trajectory.Length; i++)
            {
                var point         = trajectory[i];
                var templatePoint = template.Trajectory[i];

                point.Distance.In(templatePoint.Distance.Unit).Should().BeApproximately(templatePoint.Distance.Value, templatePoint.Distance.Value * velocityAccuracyInPercent, $"@{point.Distance:N0}");
                point.Velocity.In(templatePoint.Velocity.Unit).Should().BeApproximately(templatePoint.Velocity.Value, templatePoint.Velocity.Value * velocityAccuracyInPercent, $"@{point.Distance:N0}");

                var dropAccuracyInInch = Measurement <AngularUnit> .Convert(dropAccuracyInMOA, AngularUnit.MOA, AngularUnit.InchesPer100Yards) * templatePoint.Distance.In(DistanceUnit.Yard) / 100;

                var windageAccuracyInInch = Measurement <AngularUnit> .Convert(windageAccuracyInMOA, AngularUnit.MOA, AngularUnit.InchesPer100Yards) * templatePoint.Distance.In(DistanceUnit.Yard) / 100;

                point.Drop.In(DistanceUnit.Inch).Should().BeApproximately(templatePoint.Drop.In(DistanceUnit.Inch), dropAccuracyInInch, $"@{point.Distance:N0}");
                point.Windage.In(DistanceUnit.Inch).Should().BeApproximately(templatePoint.Windage.In(DistanceUnit.Inch), windageAccuracyInInch, $"@{point.Distance:N0}");
            }
        }
        public TableLoader(Stream table)
        {
            using var text = new StreamReader(table, Encoding.UTF8, true, 4096, true);
            CsvReader     csv   = new CsvReader(text, ";");
            List <string> units = new List <string>();

            while (csv.Read())
            {
                if (csv.FieldsCount == 0)
                {
                    continue;
                }
                if (csv[0] == "ammo")
                {
                    if (csv.FieldsCount < 6)
                    {
                        Ammunition = new Ammunition(
                            ballisticCoefficient: new BallisticCoefficient(csv[1]),
                            weight: new Measurement <WeightUnit>(csv[2]),
                            muzzleVelocity: new Measurement <VelocityUnit>(csv[3]));
                    }
                    else
                    {
                        Ammunition = new Ammunition(
                            weight: new Measurement <WeightUnit>(csv[2]),
                            ballisticCoefficient: new BallisticCoefficient(csv[1]),
                            muzzleVelocity: new Measurement <VelocityUnit>(csv[3]),
                            bulletDiameter: new Measurement <DistanceUnit>(csv[4]),
                            bulletLength: new Measurement <DistanceUnit>(csv[5]));
                    }
                }
                else if (csv[0] == "rifle")
                {
                    if (csv.FieldsCount < 5)
                    {
                        Rifle = new Rifle(
                            sight: new Sight(sightHeight: new Measurement <DistanceUnit>(csv[1]), Measurement <AngularUnit> .ZERO, Measurement <AngularUnit> .ZERO),
                            zero: new ZeroingParameters(distance: new Measurement <DistanceUnit>(csv[2]), null, null),
                            rifling: null);
                    }
                    else
                    {
                        Rifle = new Rifle(
                            sight: new Sight(sightHeight: new Measurement <DistanceUnit>(csv[1]), Measurement <AngularUnit> .ZERO, Measurement <AngularUnit> .ZERO),
                            zero: new ZeroingParameters(distance: new Measurement <DistanceUnit>(csv[2]), null, null),
                            rifling: new Rifling(new Measurement <DistanceUnit>(csv[3]), csv[4] == "left" ? TwistDirection.Left : TwistDirection.Right));
                    }
                }
                else if (csv[0] == "wind")
                {
                    Wind = new Wind(new Measurement <VelocityUnit>(csv[1]), new Measurement <AngularUnit>(csv[2]));
                }
                else if (csv[0] == "atmosphere")
                {
                    Atmosphere = new Atmosphere(
                        altitude: new Measurement <DistanceUnit>(csv[4]),
                        pressure: new Measurement <PressureUnit>(csv[3]),
                        temperature: new Measurement <TemperatureUnit>(csv[1]),
                        humidity: double.Parse(csv[2], CultureInfo.InvariantCulture) / 100.0);
                }
                else if (csv[0] == "shot")
                {
                    ShotParameters = new ShotParameters()
                    {
                        ShotAngle = new Measurement <AngularUnit>(csv[1]),
                        CantAngle = new Measurement <AngularUnit>(csv[2]),
                    };
                }
                else
                {
                    if (char.IsDigit(csv[0][0]))
                    {
                        if (units.Count == 0)
                        {
                            throw new InvalidOperationException("The header with the unit names for the table is not found");
                        }

                        var distance = new Measurement <DistanceUnit>(csv[0] + units[0]);
                        var drop     = new Measurement <DistanceUnit>(csv[1] + units[1]);
                        var windage  = new Measurement <DistanceUnit>(csv[3] + units[3]);
                        var velocity = new Measurement <VelocityUnit>(csv[5] + units[5]);
                        var mach     = double.Parse(csv[6], CultureInfo.InvariantCulture);
                        var energy   = new Measurement <EnergyUnit>(csv[7] + units[7]);
                        var time     = double.Parse(csv[8], CultureInfo.InvariantCulture);

                        mTrajectory.Add(new TrajectoryPoint(
                                            time: TimeSpan.FromSeconds(time),
                                            distance: distance,
                                            velocity: velocity,
                                            mach: mach,
                                            drop: drop,
                                            windage: windage,
                                            energy: energy,
                                            optimalGameWeight: Measurement <WeightUnit> .ZERO
                                            ));
                    }
                    else
                    {
                        for (int i = 0; i < csv.FieldsCount; i++)
                        {
                            units.Add(csv[i]);
                        }
                    }
                }
            }
        }
Пример #7
0
        internal static TrajectoryPoint[] M193(bool hasWind, Measurement <DistanceUnit> step)
        {
            //define M193 projectile out of 20 inch barrel
            var ammo = new Ammunition(
                weight: new Measurement <WeightUnit>(55, WeightUnit.Grain),
                ballisticCoefficient: new BallisticCoefficient(0.202, DragTableId.G1),
                muzzleVelocity: new Measurement <VelocityUnit>(3240, VelocityUnit.FeetPerSecond),
                bulletDiameter: new Measurement <DistanceUnit>(0.224, DistanceUnit.Inch),
                bulletLength: new Measurement <DistanceUnit>(0.76, DistanceUnit.Inch));

            //define ACOG scope
            var sight = new Sight(
                sightHeight: new Measurement <DistanceUnit>(3.5, DistanceUnit.Inch),
                verticalClick: new Measurement <AngularUnit>(1.0 / 3.0, AngularUnit.InchesPer100Yards),
                horizontalClick: new Measurement <AngularUnit>(1.0 / 3.0, AngularUnit.InchesPer100Yards)
                );

            //M16 rifling
            var rifling = new Rifling(
                riflingStep: new Measurement <DistanceUnit>(12, DistanceUnit.Inch),
                direction: TwistDirection.Right);

            //standard 100 yard ACOG zeroing
            var zero = new ZeroingParameters(
                distance: new Measurement <DistanceUnit>(100, DistanceUnit.Yard),
                ammunition: null,
                atmosphere: null
                );

            //define rifle by sight, zeroing and rifling parameters
            var rifle = new Rifle(sight: sight, zero: zero, rifling: rifling);

            //define atmosphere
            var atmosphere = new Atmosphere(
                altitude: new Measurement <DistanceUnit>(0, DistanceUnit.Foot),
                pressure: new Measurement <PressureUnit>(29.92, PressureUnit.InchesOfMercury),
                pressureAtSeaLevel: false,
                temperature: new Measurement <TemperatureUnit>(59, TemperatureUnit.Fahrenheit),
                humidity: 0.78);

            var calc = new TrajectoryCalculator();

            //shot parameters
            var shot = new ShotParameters()
            {
                MaximumDistance = new Measurement <DistanceUnit>(1000, DistanceUnit.Yard),
                Step            = step,
                //calculate sight angle for the specified zero distance
                SightAngle = calc.SightAngle(ammo, rifle, atmosphere)
            };

            //define winds

            Wind[] wind = hasWind ? new Wind[2]
            {
                new Wind()
                {
                    Direction    = new Measurement <AngularUnit>(45, AngularUnit.Degree),
                    Velocity     = new Measurement <VelocityUnit>(10, VelocityUnit.MilesPerHour),
                    MaximumRange = new Measurement <DistanceUnit>(500, DistanceUnit.Yard),
                },
                new Wind()
                {
                    Direction = new Measurement <AngularUnit>(15, AngularUnit.Degree),
                    Velocity  = new Measurement <VelocityUnit>(5, VelocityUnit.MilesPerHour),
                }
            } : null;

            //calculate trajectory
            return(calc.Calculate(ammo, rifle, atmosphere, shot, wind));
        }