Bu bölümün laboratuvarı, kitaptaki örnekleri yeniden üretmek ve sayısal sonuçları incelemek için hazırlanmıştır. Matematiksel tanımlar, ispatlar ve sorular kitapta yer alır.
Laboratuvar kodu
"""Bölüm 13: ideal eliptik akustik/optik yansıtıcı laboratuvarı.
Model yalnız iki boyutlu bir elips kesitini ve geometrik ışın yansımasını
temsil eder. Kırınım, soğurma, faz, yüzey kusuru, kaynak yönlülüğü ve gerçek
bir yapının akustik ya da optik performansı modele dahil değildir.
"""
from __future__ import annotations
import numpy as np
from agbook import (
canonical_array_sha256,
ellipse_algebraic_residuals,
ellipse_focal_sum_residuals,
ellipse_frame_from_center_axes,
ellipse_points,
ellipse_reflection_diagnostics,
ellipse_tangent_line,
focus_directrix_diagnostics,
rotation_matrix_2d,
)
def main() -> None:
semi_major_m = 10.0
semi_minor_m = 6.0
center_m = np.array([0.0, 0.0])
major_axis = np.array([1.0, 0.0])
frame = ellipse_frame_from_center_axes(
center_m,
major_axis,
semi_major_m,
semi_minor_m,
)
parameters_rad = np.linspace(0.0, 2.0 * np.pi, 12, endpoint=False)
boundary_points_m = ellipse_points(
frame.center,
frame.major_direction,
frame.semi_major,
frame.semi_minor,
parameters_rad,
)
algebraic_residuals = ellipse_algebraic_residuals(
boundary_points_m,
frame.center,
frame.major_direction,
frame.semi_major,
frame.semi_minor,
)
focal_sum_residuals_m = ellipse_focal_sum_residuals(
boundary_points_m,
frame.first_focus,
frame.second_focus,
frame.semi_major,
)
focus_directrix = focus_directrix_diagnostics(
boundary_points_m,
frame.second_focus,
frame.second_directrix,
frame.eccentricity,
reference_scale=2.0 * frame.semi_major,
)
reflection = ellipse_reflection_diagnostics(
frame.center,
frame.major_direction,
frame.semi_major,
frame.semi_minor,
parameters_rad,
)
tangent_lines = np.vstack(
[
ellipse_tangent_line(
frame.center,
frame.major_direction,
frame.semi_major,
frame.semi_minor,
parameter,
)
for parameter in parameters_rad
]
)
tangent_point_residuals_m = np.sum(
tangent_lines[:, :2] * boundary_points_m,
axis=1,
) + tangent_lines[:, 2]
np.testing.assert_allclose(algebraic_residuals, 0.0, atol=4e-15)
np.testing.assert_allclose(focal_sum_residuals_m, 0.0, atol=4e-15)
np.testing.assert_allclose(tangent_point_residuals_m, 0.0, atol=4e-15)
np.testing.assert_allclose(reflection.focal_path_lengths, 20.0, atol=4e-14)
assert focus_directrix.maximum_absolute_residual < 4e-15
assert reflection.maximum_direction_error < 2e-15
assert reflection.maximum_focus_line_residual < 2e-14
rotation = rotation_matrix_2d(np.deg2rad(31.0))
translation_m = np.array([13.0, -7.0])
moved_center_m = rotation @ frame.center + translation_m
moved_axis = rotation @ frame.major_direction
moved = ellipse_reflection_diagnostics(
moved_center_m,
moved_axis,
frame.semi_major,
frame.semi_minor,
parameters_rad,
)
expected_moved_points_m = boundary_points_m @ rotation.T + translation_m
np.testing.assert_allclose(moved.points, expected_moved_points_m, atol=4e-14)
np.testing.assert_allclose(
moved.reflected_directions,
reflection.reflected_directions @ rotation.T,
atol=4e-14,
)
scaled = ellipse_frame_from_center_axes(
1000.0 * frame.center,
frame.major_direction,
1000.0 * frame.semi_major,
1000.0 * frame.semi_minor,
)
np.testing.assert_allclose(scaled.eccentricity, frame.eccentricity)
np.testing.assert_allclose(scaled.focal_distance, 1000.0 * frame.focal_distance)
signature_values = np.concatenate(
[
np.array(
[
frame.semi_major,
frame.semi_minor,
frame.focal_distance,
frame.eccentricity,
]
),
frame.center,
frame.first_focus,
frame.second_focus,
frame.first_directrix,
frame.second_directrix,
parameters_rad,
boundary_points_m.ravel(),
tangent_lines.ravel(),
reflection.reflected_directions.ravel(),
reflection.focal_path_lengths,
rotation.ravel(),
translation_m,
moved.points.ravel(),
]
)
print("birim: m")
print("model: sentetik_iki_boyutlu_ideal_eliptik_yansitici")
print("gercek_akustik_veya_optik_tasarim_mi: False")
print("yari_buyuk_eksen_m:", frame.semi_major)
print("yari_kucuk_eksen_m:", frame.semi_minor)
print("dogrusal_dismerkezlik_m:", frame.focal_distance)
print("dismerkezlik:", frame.eccentricity)
print("birinci_odak_m:", frame.first_focus)
print("ikinci_odak_m:", frame.second_focus)
print("sinir_noktasi_sayisi:", boundary_points_m.shape[0])
print("sabit_kirik_yol_m:", 2.0 * frame.semi_major)
print(
"en_buyuk_cebirsel_artik:",
f"{np.max(np.abs(algebraic_residuals)):.3e}",
)
print(
"en_buyuk_odak_toplam_artigi_m:",
f"{np.max(np.abs(focal_sum_residuals_m)):.3e}",
)
print(
"en_buyuk_odak_dogrultman_artigi_m:",
f"{focus_directrix.maximum_absolute_residual:.3e}",
)
print(
"en_buyuk_teget_nokta_artigi_m:",
f"{np.max(np.abs(tangent_point_residuals_m)):.3e}",
)
print(
"en_buyuk_yansima_yon_hatasi:",
f"{reflection.maximum_direction_error:.3e}",
)
print(
"en_buyuk_odak_cizgisi_artigi_m:",
f"{reflection.maximum_focus_line_residual:.3e}",
)
print(
"rijit_noktalar_korundu_mu:",
bool(np.allclose(moved.points, expected_moved_points_m)),
)
print("mm_olceginde_dogrusal_dismerkezlik:", scaled.focal_distance)
print("bilimsel_imza:", canonical_array_sha256(signature_values))
if __name__ == "__main__":
main()
Doğrulama çalıştırmasının çıktısı
birim: m
model: sentetik_iki_boyutlu_ideal_eliptik_yansitici
gercek_akustik_veya_optik_tasarim_mi: False
yari_buyuk_eksen_m: 10.0
yari_kucuk_eksen_m: 6.0
dogrusal_dismerkezlik_m: 8.0
dismerkezlik: 0.8
birinci_odak_m: [-8. 0.]
ikinci_odak_m: [8. 0.]
sinir_noktasi_sayisi: 12
sabit_kirik_yol_m: 20.0
en_buyuk_cebirsel_artik: 2.220e-16
en_buyuk_odak_toplam_artigi_m: 0.000e+00
en_buyuk_odak_dogrultman_artigi_m: 3.553e-15
en_buyuk_teget_nokta_artigi_m: 1.776e-15
en_buyuk_yansima_yon_hatasi: 5.901e-16
en_buyuk_odak_cizgisi_artigi_m: 8.882e-15
rijit_noktalar_korundu_mu: True
mm_olceginde_dogrusal_dismerkezlik: 8000.0
bilimsel_imza: 6051839a41c2e2967ac4503ce684f862c6324ab8aea3a27b2a6ae219e9ba80fb
Metindeki Python kodları
# Kitaptaki kod blokları; bu dosya içinde sırayla çalıştırılır.
# --- 1. Bölüm 13: elips çerçevesi ve sınır noktaları ---
import numpy as np
from agbook import (
ellipse_algebraic_residuals,
ellipse_focal_sum_residuals,
ellipse_frame_from_center_axes,
ellipse_points,
ellipse_reflection_diagnostics,
)
a, b = 10.0, 6.0 # metre
frame = ellipse_frame_from_center_axes([0., 0.], [1., 0.], a, b)
t = np.linspace(0.0, 2.0 * np.pi, 12, endpoint=False)
points = ellipse_points(frame.center, frame.major_direction, a, b, t)
r_alg = ellipse_algebraic_residuals(
points, frame.center, frame.major_direction, a, b
)
r_sum = ellipse_focal_sum_residuals(
points, frame.first_focus, frame.second_focus, a
)
reflection = ellipse_reflection_diagnostics(
frame.center, frame.major_direction, a, b, t
)
print(frame.focal_distance, frame.eccentricity)
print(np.max(np.abs(r_alg)), np.max(np.abs(r_sum)))
print(reflection.maximum_direction_error)
# --- 2. Bölüm 13 laboratuvarı: teğet ve rijit değişmezlik ---
from agbook import ellipse_tangent_line, rotation_matrix_2d
tangents = np.vstack([
ellipse_tangent_line(frame.center, frame.major_direction, a, b, value)
for value in t
])
tangent_residuals = np.sum(tangents[:, :2] * points, axis=1) + tangents[:, 2]
Q = rotation_matrix_2d(np.deg2rad(31.0))
shift = np.array([13.0, -7.0]) # metre
moved = ellipse_reflection_diagnostics(
Q @ frame.center + shift, Q @ frame.major_direction, a, b, t
)
expected_points = points @ Q.T + shift
print(np.max(np.abs(tangent_residuals)))
print(np.max(np.abs(moved.points - expected_points)))
print(np.max(np.abs(
moved.reflected_directions - reflection.reflected_directions @ Q.T
)))
Kaydedilen çıktı
1. Bölüm 13: elips çerçevesi ve sınır noktaları
8.0 0.8
2.220446049250313e-16 0.0
5.900916318210353e-16
2. Bölüm 13 laboratuvarı: teğet ve rijit değişmezlik
1.7763568394002505e-15
1.7763568394002505e-15
6.661338147750939e-16
Çözümlerdeki Python kodları
# Kitaptaki kod blokları; bu dosya içinde sırayla çalıştırılır.
# --- 1. İki elips kurucusunun eşdeğerliği ---
import numpy as np
from agbook import (
ellipse_frame_from_center_axes,
ellipse_frame_from_foci,
)
first = ellipse_frame_from_center_axes([1., -2.], [2., 1.], 7., 4.)
second = ellipse_frame_from_foci(
first.first_focus, first.second_focus, first.semi_major
)
for name in ("center", "first_focus", "second_focus", "major_direction"):
assert np.allclose(getattr(first, name), getattr(second, name))
assert np.isclose(first.semi_minor, second.semi_minor)
assert np.isclose(first.eccentricity, second.eccentricity)
print(first.focal_distance, first.eccentricity)
# --- 2. Üyelik ve teğet artıkları ---
import numpy as np
from agbook import (
ellipse_algebraic_residuals,
ellipse_focal_sum_residuals,
ellipse_frame_from_center_axes,
ellipse_points,
ellipse_tangent_line,
)
frame = ellipse_frame_from_center_axes([0., 0.], [1., 0.], 5., 3.)
t = np.linspace(0., 2. * np.pi, 8, endpoint=False)
points = ellipse_points([0., 0.], [1., 0.], 5., 3., t)
r_alg = ellipse_algebraic_residuals(points, [0., 0.], [1., 0.], 5., 3.)
r_sum = ellipse_focal_sum_residuals(
points, frame.first_focus, frame.second_focus, 5.
)
lines = np.vstack([
ellipse_tangent_line([0., 0.], [1., 0.], 5., 3., value)
for value in t
])
r_tan = np.sum(lines[:, :2] * points, axis=1) + lines[:, 2]
print(np.max(np.abs(r_alg)), np.max(np.abs(r_sum)), np.max(np.abs(r_tan)))
assert np.max(np.abs(r_alg)) < 2e-15
assert np.max(np.abs(r_sum)) < 1e-14
assert np.max(np.abs(r_tan)) < 1e-14
# --- 3. Yansımanın rijit hareket altında kovaryantlığı ---
import numpy as np
from agbook import ellipse_reflection_diagnostics, rotation_matrix_2d
t = np.linspace(0., 2. * np.pi, 19, endpoint=False)
before = ellipse_reflection_diagnostics([0., 0.], [1., 0.], 10., 6., t)
Q = rotation_matrix_2d(np.deg2rad(37.))
shift = np.array([5., -3.])
after = ellipse_reflection_diagnostics(shift, Q @ np.array([1., 0.]), 10., 6., t)
assert np.allclose(after.points, before.points @ Q.T + shift)
assert np.allclose(
after.reflected_directions, before.reflected_directions @ Q.T
)
assert np.allclose(after.focal_path_lengths, before.focal_path_lengths)
print(before.maximum_direction_error, after.maximum_direction_error)
# --- 4. Ölçek değişmezliği ve açık sınır hataları ---
import numpy as np
from agbook import (
ellipse_frame_from_center_axes,
ellipse_points,
ellipse_focal_sum_residuals,
ellipse_reflection_diagnostics,
)
t = np.array([0.2, 1.1, 2.7])
m = ellipse_frame_from_center_axes([0., 0.], [1., 0.], 5., 3.)
mm = ellipse_frame_from_center_axes([0., 0.], [1., 0.], 5000., 3000.)
assert np.isclose(mm.focal_distance, 1000. * m.focal_distance)
assert np.isclose(mm.eccentricity, m.eccentricity)
p = ellipse_points([0., 0.], [1., 0.], 5., 3., t) + np.array([0.01, 0.])
r_m = ellipse_focal_sum_residuals(p, m.first_focus, m.second_focus, 5.)
r_mm = ellipse_focal_sum_residuals(
1000. * p, mm.first_focus, mm.second_focus, 5000.
)
assert np.allclose(r_mm, 1000. * r_m)
for bad in ((5., 5.), (3., 5.)):
try:
ellipse_frame_from_center_axes([0., 0.], [1., 0.], *bad)
except ValueError as error:
print(type(error).__name__, str(error))
Kaydedilen çıktı
1. İki elips kurucusunun eşdeğerliği
5.744562646538029 0.8206518066482898
2. Üyelik ve teğet artıkları
1.1102230246251565e-16 0.0 4.440892098500626e-16
3. Yansımanın rijit hareket altında kovaryantlığı
4.577566798522237e-16 6.280369834735101e-16
4. Ölçek değişmezliği ve açık sınır hataları
ValueError Normal elips için semi_major > semi_minor > 0 olmalıdır; eşitlik çember sınırıdır.
ValueError Normal elips için semi_major > semi_minor > 0 olmalıdır; eşitlik çember sınırıdır.
Çalıştırma rehberi
Önce tam Python paketini indirin ve arşivi açın. Aşağıdaki komutları arşivin üst klasöründen başlatın. İlk kurulum internet bağlantısı ve Python 3.12 veya 3.13 gerektirir. Bağımlılıklar sabittir; sistem Python'unu değiştirmemek için ayrı sanal ortam kullanılır.
macOS / Linux
cd analitik-geometri-python-v1.0
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
python labs/bolum_13_elips_yansima.py
python -m pytestWindows PowerShell
cd analitik-geometri-python-v1.0
py -3.13 -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[dev]"
.venv\Scripts\python.exe labs/bolum_13_elips_yansima.py
.venv\Scripts\python.exe -m pytest