Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring to reduce confusing terms #90

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions examples/kanik_50bmg_aid_shooting.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,24 @@

def calculate_lead_angle(target_speed, target_size, bullet_speed, initial_distance, time_of_flight):
"""
Розрахунок кута упередження маючи швидкість і розмір цілі, швидкість кулі, початкову відстань до цілі.

:param target_speed: Швидкість цілі (м/с)
:param target_size: Довжина цілі (м)
:param bullet_speed: Швидкість кулі (м/с)
:param initial_distance: Початкова відстань до цілі (м)
:return: Кут упередження в градусах
Calculation of the lead angle given the target speed and size, bullet speed, and initial distance to the target.

:param target_speed: Target speed (m/s)
:param target_size: Target length (m)
:param bullet_speed: Bullet speed (m/s)
:param initial_distance: Initial distance to the target (m)
:param time_of_flight: Time of flight (s)
:return: Lead angle in degrees
"""
# Час польоту кулі
# time_of_flight = initial_distance / bullet_speed

# Відстань, яку пройде ніс цілі
# distance_nose_travel = target_speed * time_of_flight + target_size
distance_nose_travel = target_speed * time_of_flight + target_size

# Обчислення кута упередження
# Distance the target's nose will travel
distance_nose_travel = target_speed * time_of_flight + target_size

lead_angle = math.atan(distance_nose_travel / initial_distance)

# Перетворення кута в градуси
# Converting the angle to degrees
lead_angle_degrees = math.degrees(lead_angle)

return lead_angle_degrees
Expand Down
20 changes: 10 additions & 10 deletions py_ballisticcalc/munition.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,35 +86,35 @@ def get_sfp_step(click_size: Union[Angular, AbstractUnitType]):
return Sight.ReticleStep(_v_step, _v_step)

def get_adjustment(self, target_distance: Distance,
drop_adj: Angular, windage_adj: Angular,
drop_angle: Angular, windage_angle: Angular,
magnification: float):
"""Calculate adjustment for target distance and magnification"""

if self.focal_plane == Sight.FocalPlane.SFP:
steps = self._adjust_sfp_reticle_steps(target_distance, magnification)
return Sight.Clicks(
drop_adj.raw_value / steps.vertical.raw_value,
windage_adj.raw_value / steps.horizontal.raw_value
drop_angle.raw_value / steps.vertical.raw_value,
windage_angle.raw_value / steps.horizontal.raw_value
)
if self.focal_plane == Sight.FocalPlane.FFP:
return Sight.Clicks(
drop_adj.raw_value / self.v_click_size.raw_value,
windage_adj.raw_value / self.h_click_size.raw_value
drop_angle.raw_value / self.v_click_size.raw_value,
windage_angle.raw_value / self.h_click_size.raw_value
)
if self.focal_plane == Sight.FocalPlane.LWIR:
# adjust clicks to magnification
return Sight.Clicks(
drop_adj.raw_value / (self.v_click_size.raw_value / magnification),
windage_adj.raw_value / (self.h_click_size.raw_value / magnification)
drop_angle.raw_value / (self.v_click_size.raw_value / magnification),
windage_angle.raw_value / (self.h_click_size.raw_value / magnification)
)
raise AttributeError("Wrong focal_plane")

def get_trajectory_adjustment(self, trajectory_point: 'TrajectoryData', magnification: float) -> Clicks:
"""Calculate adjustment for target distance and magnification for `TrajectoryData` instance"""

return self.get_adjustment(trajectory_point.distance,
trajectory_point.drop_adj,
trajectory_point.windage_adj,
return self.get_adjustment(trajectory_point.x,
trajectory_point.drop_angle,
trajectory_point.windage_angle,
magnification)


Expand Down
16 changes: 8 additions & 8 deletions py_ballisticcalc/trajectory_calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def zero_angle(self, shot_info: Shot, distance: Distance) -> Angular:
while zero_finding_error > cZeroFindingAccuracy and iterations_count < cMaxIterations:
# Check height of trajectory at the zero distance (using current self.barrel_elevation)
t = self._trajectory(shot_info, maximum_range, zero_distance, TrajFlag.NONE)[0]
height = t.height >> Distance.Foot
height = t.y >> Distance.Foot
zero_finding_error = math.fabs(height - height_at_zero)
if zero_finding_error > cZeroFindingAccuracy:
# Adjust barrel elevation to close height at zero distance
Expand Down Expand Up @@ -437,21 +437,21 @@ def create_trajectory_row(time: float, range_vector: Vector, velocity_vector: Ve
:return: A TrajectoryData object representing the trajectory data.
"""
windage = range_vector.z + spin_drift
drop_adjustment = get_correction(range_vector.x, range_vector.y)
windage_adjustment = get_correction(range_vector.x, windage)
drop_angle = get_correction(range_vector.x, range_vector.y)
windage_angle = get_correction(range_vector.x, windage)
trajectory_angle = math.atan(velocity_vector.y / velocity_vector.x)

return TrajectoryData(
time=time,
distance=Distance.Foot(range_vector.x),
x=Distance.Foot(range_vector.x),
velocity=Velocity.FPS(velocity),
mach=velocity / mach,
height=Distance.Foot(range_vector.y),
y=Distance.Foot(range_vector.y),
target_drop=Distance.Foot((range_vector.y - range_vector.x * math.tan(look_angle)) * math.cos(look_angle)),
drop_adj=Angular.Radian(drop_adjustment - (look_angle if range_vector.x else 0)),
drop_angle=Angular.Radian(drop_angle - (look_angle if range_vector.x else 0)),
windage=Distance.Foot(windage),
windage_adj=Angular.Radian(windage_adjustment),
look_distance=Distance.Foot(range_vector.x / math.cos(look_angle)),
windage_angle=Angular.Radian(windage_angle),
distance=Distance.Foot(range_vector.x / math.cos(look_angle)),
angle=Angular.Radian(trajectory_angle),
density_factor=density_factor - 1,
drag=drag,
Expand Down
84 changes: 42 additions & 42 deletions py_ballisticcalc/trajectory_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ class TrajectoryData(NamedTuple):

Attributes:
time (float): bullet flight time
distance (Distance): x-axis coordinate
x (Distance): x-axis coordinate
velocity (Velocity): velocity
mach (float): velocity in Mach prefer_units
height (Distance): y-axis coordinate
y (Distance): y-axis coordinate
target_drop (Distance): drop relative to sight-line
drop_adj (Angular): sight adjustment to zero target_drop at this distance
drop_angle (Angular): sight adjustment to zero target_drop at this distance
windage (Distance):
windage_adj (Angular):
look_distance (Distance): sight-line distance = .distance/cosine(look_angle)
# look_height (Distance): y-coordinate of sight-line = .distance*tan(look_angle)
windage_angle (Angular):
distance (Distance): sight-line distance = .x/cosine(look_angle)
# look_height (Distance): y-coordinate of sight-line = .x*tan(look_angle)
angle (Angular): Angle of velocity vector relative to x-axis
density_factor (float): Ratio of air density here to standard density
drag (float): Current drag coefficient
Expand All @@ -72,15 +72,15 @@ class TrajectoryData(NamedTuple):
"""

time: float
distance: Distance
x: Distance
velocity: Velocity
mach: float
height: Distance
y: Distance
target_drop: Distance
drop_adj: Angular
drop_angle: Angular
windage: Distance
windage_adj: Angular
look_distance: Distance
windage_angle: Angular
distance: Distance
angle: Angular
density_factor: float
drag: float
Expand All @@ -99,15 +99,15 @@ def _fmt(v: AbstractUnit, u: Unit):

return (
f'{self.time:.3f} s',
_fmt(self.distance, PreferredUnits.distance),
_fmt(self.x, PreferredUnits.distance),
_fmt(self.velocity, PreferredUnits.velocity),
f'{self.mach:.2f} mach',
_fmt(self.height, PreferredUnits.drop),
_fmt(self.y, PreferredUnits.drop),
_fmt(self.target_drop, PreferredUnits.drop),
_fmt(self.drop_adj, PreferredUnits.adjustment),
_fmt(self.drop_angle, PreferredUnits.adjustment),
_fmt(self.windage, PreferredUnits.drop),
_fmt(self.windage_adj, PreferredUnits.adjustment),
_fmt(self.look_distance, PreferredUnits.distance),
_fmt(self.windage_angle, PreferredUnits.adjustment),
_fmt(self.distance, PreferredUnits.distance),
_fmt(self.angle, PreferredUnits.angular),
f'{self.density_factor:.3e}',
f'{self.drag:.3f}',
Expand All @@ -123,15 +123,15 @@ def in_def_units(self) -> tuple:
"""
return (
self.time,
self.distance >> PreferredUnits.distance,
self.x >> PreferredUnits.distance,
self.velocity >> PreferredUnits.velocity,
self.mach,
self.height >> PreferredUnits.drop,
self.y >> PreferredUnits.drop,
self.target_drop >> PreferredUnits.drop,
self.drop_adj >> PreferredUnits.adjustment,
self.drop_angle >> PreferredUnits.adjustment,
self.windage >> PreferredUnits.drop,
self.windage_adj >> PreferredUnits.adjustment,
self.look_distance >> PreferredUnits.distance,
self.windage_angle >> PreferredUnits.adjustment,
self.distance >> PreferredUnits.distance,
self.angle >> PreferredUnits.angular,
self.density_factor,
self.drag,
Expand All @@ -150,24 +150,24 @@ class DangerSpace(NamedTuple):
look_angle: Angular

def __str__(self) -> str:
return f'Danger space at {self.at_range.distance << PreferredUnits.distance} ' \
return f'Danger space at {self.at_range.x << PreferredUnits.distance} ' \
+ f'for {self.target_height << PreferredUnits.drop} tall target ' \
+ (f'at {self.look_angle << Angular.Degree} look-angle ' if self.look_angle != 0 else '') \
+ f'ranges from {self.begin.distance << PreferredUnits.distance} ' \
+ f'to {self.end.distance << PreferredUnits.distance}'
+ f'ranges from {self.begin.x << PreferredUnits.distance} ' \
+ f'to {self.end.x << PreferredUnits.distance}'

def overlay(self, ax: 'Axes', label: Optional[str] = None): # type: ignore
"""Highlights danger-space region on plot"""
if matplotlib is None or not Polygon:
raise ImportError("Use `pip install py_ballisticcalc[charts]` to get results as a plot")

cosine = math.cos(self.look_angle >> Angular.Radian)
begin_dist = (self.begin.distance >> PreferredUnits.distance) * cosine
begin_drop = (self.begin.height >> PreferredUnits.drop) * cosine
end_dist = (self.end.distance >> PreferredUnits.distance) * cosine
end_drop = (self.end.height >> PreferredUnits.drop) * cosine
range_dist = (self.at_range.distance >> PreferredUnits.distance) * cosine
range_drop = (self.at_range.height >> PreferredUnits.drop) * cosine
begin_dist = (self.begin.x >> PreferredUnits.distance) * cosine
begin_drop = (self.begin.y >> PreferredUnits.drop) * cosine
end_dist = (self.end.x >> PreferredUnits.distance) * cosine
end_drop = (self.end.y >> PreferredUnits.drop) * cosine
range_dist = (self.at_range.x >> PreferredUnits.distance) * cosine
range_drop = (self.at_range.y >> PreferredUnits.drop) * cosine
h = self.target_height >> PreferredUnits.drop

# Target position and height:
Expand All @@ -182,7 +182,7 @@ def overlay(self, ax: 'Axes', label: Optional[str] = None): # type: ignore
edgecolor='none', facecolor='r', alpha=0.3)
ax.add_patch(polygon)
if label is None: # Add default label
label = f"Danger space\nat {self.at_range.distance << PreferredUnits.distance}"
label = f"Danger space\nat {self.at_range.x << PreferredUnits.distance}"
if label != '':
ax.text(begin_dist + (end_dist - begin_dist) / 2, end_drop, label,
linespacing=1.2, fontsize=PLOT_FONT_SIZE, ha='center', va='top')
Expand Down Expand Up @@ -326,29 +326,29 @@ def plot(self, look_angle: Optional[Angular] = None) -> 'Axes': # type: ignore
"Use Calculator.fire(..., extra_data=True)")
font_size = PLOT_FONT_SIZE
df = self.dataframe()
ax = df.plot(x='distance', y=['height'], ylabel=PreferredUnits.drop.symbol)
max_range = self.trajectory[-1].distance >> PreferredUnits.distance
ax = df.plot(x='x', y=['y'], ylabel=PreferredUnits.drop.symbol)
max_range = self.trajectory[-1].x >> PreferredUnits.distance

for p in self.trajectory:
if TrajFlag(p.flag) & TrajFlag.ZERO:
ax.plot([p.distance >> PreferredUnits.distance, p.distance >> PreferredUnits.distance],
[df['height'].min(), p.height >> PreferredUnits.drop], linestyle=':')
ax.text((p.distance >> PreferredUnits.distance) + max_range / 100, df['height'].min(),
ax.plot([p.x >> PreferredUnits.distance, p.x >> PreferredUnits.distance],
[df['y'].min(), p.y >> PreferredUnits.drop], linestyle=':')
ax.text((p.x >> PreferredUnits.distance) + max_range / 100, df['y'].min(),
f"{(TrajFlag(p.flag) & TrajFlag.ZERO).name}",
fontsize=font_size, rotation=90)
if TrajFlag(p.flag) & TrajFlag.MACH:
ax.plot([p.distance >> PreferredUnits.distance, p.distance >> PreferredUnits.distance],
[df['height'].min(), p.height >> PreferredUnits.drop], linestyle=':')
ax.text((p.distance >> PreferredUnits.distance) + max_range / 100, df['height'].min(),
ax.plot([p.x >> PreferredUnits.distance, p.x >> PreferredUnits.distance],
[df['y'].min(), p.y >> PreferredUnits.drop], linestyle=':')
ax.text((p.x >> PreferredUnits.distance) + max_range / 100, df['y'].min(),
"Mach 1", fontsize=font_size, rotation=90)

max_range_in_drop_units = self.trajectory[-1].distance >> PreferredUnits.drop
max_range_in_drop_units = self.trajectory[-1].x >> PreferredUnits.drop
# Sight line
x_sight = [0, df.distance.max()]
x_sight = [0, df.x.max()]
y_sight = [0, max_range_in_drop_units * math.tan(look_angle >> Angular.Radian)]
ax.plot(x_sight, y_sight, linestyle='--', color=[.3, 0, .3, .5])
# Barrel pointing line
x_bbl = [0, df.distance.max()]
x_bbl = [0, df.x.max()]
y_bbl = [-(self.shot.weapon.sight_height >> PreferredUnits.drop),
max_range_in_drop_units * math.tan(self.trajectory[0].angle >> Angular.Radian)
- (self.shot.weapon.sight_height >> PreferredUnits.drop)]
Expand Down
Loading
Loading