ff5f089dc1
- 标签顺序:几何与安装 放到 测试序列 之前 - 序列点增加可选 uv_px(向后兼容),点表新增 U/V 列;加入所选点、删除所选、 送到标定页(按 U/V 经同一套求解加入标定队列并切换页面) - 已选点结果改显示在选点区状态行,不再写入全局顶部状态条 - 序列页左上区改紧凑:名称与备注同一行,分“阵列”“运动参数”两页; 运动参数每行三组,输入框改用 compactField - 新增阵列工具(array_plan.py、ui/array_tool.py):UV 规则网格(可蛇形遍历)与 阶段预设,逐点检查是否在曲面内、是否留有边距,候选点实时预览在 2D 图上, 只有可用点才能加入,已在序列里的点不重复加入 - 2D 平面图:标记改为缩放后再绘制并加深色描边,修复缩小后点不清; 底图可选 原图/灰度/变暗/仅轮廓,点色可选 黄/白/青/橙/灰(默认灰度+黄,写入偏好); 序列点带编号并连线显示遍历顺序,选中行高亮 - 新增测试 test_sequence_uv、test_sequence_to_capture、test_array_plan、test_array_tool
128 lines
4.8 KiB
Python
128 lines
4.8 KiB
Python
"""The array tool and the 2D map's look: what the operator sees and what the tool offers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
from orisys_app_shared.i18n import t
|
|
from orisys_autocal.array_plan import Candidate
|
|
from orisys_autocal.ui.sensor_panel import FlatSurfaceView
|
|
from PySide6.QtGui import QColor
|
|
|
|
|
|
def _synthetic_flat(size: int = 64):
|
|
from orisys_autocal.sensor.uv_flat import FlatSurface
|
|
|
|
image = np.zeros((size, size, 3), dtype=np.uint8)
|
|
image[..., 2] = 200 # a plain blue map: any yellow on it is a mark
|
|
return FlatSurface(
|
|
size_hw=(size, size),
|
|
image_rgb=image,
|
|
positions_mm=np.zeros((size, size, 3)),
|
|
normals=np.tile(np.array([0.0, 0.0, 1.0]), (size, size, 1)),
|
|
face_index=np.zeros((size, size), dtype=np.int32),
|
|
uv_min=(0.0, 0.0),
|
|
uv_max=(1.0, 1.0),
|
|
)
|
|
|
|
|
|
def test_marks_stay_visible_when_the_map_is_scaled_down(qt_app):
|
|
view = FlatSurfaceView()
|
|
view.resize(32, 32) # half the map's size
|
|
view.set_flat(_synthetic_flat(64))
|
|
view.set_marker_colour("#ffd60a")
|
|
view.set_sequence_points([(32, 32, "", False)])
|
|
shown = view.pixmap().toImage()
|
|
centre = QColor(shown.pixel(shown.width() // 2, shown.height() // 2))
|
|
# The mark is drawn after the scale, so its colour is at the centre of the
|
|
# shown image instead of being smeared into the blue by the downscale.
|
|
assert centre.red() > 220 and centre.green() > 180 and centre.blue() < 80
|
|
|
|
|
|
def test_the_background_can_be_changed_and_marks_survive_it(qt_app):
|
|
view = FlatSurfaceView()
|
|
view.resize(64, 64)
|
|
view.set_flat(_synthetic_flat(64))
|
|
before = QColor(view.pixmap().toImage().pixel(2, 2))
|
|
for mode in ("gray", "dim", "outline"):
|
|
view.set_background(mode)
|
|
after = QColor(view.pixmap().toImage().pixel(2, 2))
|
|
assert after != before, mode
|
|
assert view.background == mode
|
|
view.set_background("nonsense")
|
|
assert view.background == "original"
|
|
|
|
|
|
def test_unusable_candidates_are_drawn_apart_from_usable_ones(qt_app):
|
|
view = FlatSurfaceView()
|
|
view.resize(64, 64)
|
|
view.set_flat(_synthetic_flat(64))
|
|
view.set_marker_colour("#ffd60a")
|
|
view.set_candidates([(32, 32, False)])
|
|
shown = view.pixmap().toImage()
|
|
red_pixels = sum(
|
|
1
|
|
for x in range(24, 41)
|
|
for y in range(24, 41)
|
|
if QColor(shown.pixel(x, y)).red() > 200 and QColor(shown.pixel(x, y)).green() < 110
|
|
)
|
|
assert red_pixels > 0
|
|
|
|
|
|
def test_the_look_is_chosen_on_the_page_and_reported(make_window):
|
|
window = make_window()
|
|
panel = window.finger_panel
|
|
seen: list[tuple[str, str]] = []
|
|
panel.viewStyleChanged.connect(lambda mode, colour: seen.append((mode, colour)))
|
|
panel.bg_combo.setCurrentIndex(panel.bg_combo.findData("dim"))
|
|
panel.colour_combo.setCurrentIndex(panel.colour_combo.findData("white"))
|
|
assert panel.view_style() == ("dim", "white")
|
|
assert seen[-1] == ("dim", "white")
|
|
assert window.prefs["finger_view_background"] == "dim"
|
|
assert panel.view.marker_colour == QColor("#ffffff")
|
|
window.close()
|
|
|
|
|
|
def test_the_grid_has_rows_times_columns_candidates_and_follows_its_fields(make_window):
|
|
window = make_window()
|
|
tool = window.sequence_panel.array_tool
|
|
assert len(tool.candidates()) == 9
|
|
tool.spin("rows").setValue(2)
|
|
tool.spin("cols").setValue(5)
|
|
assert len(tool.candidates()) == 10
|
|
tool.mode_combo.setCurrentIndex(tool.mode_combo.findData("preset"))
|
|
assert tool.mode == "preset"
|
|
tool.preset_combo.setCurrentIndex(tool.preset_combo.findData("stage0"))
|
|
assert tool.candidates() == [("C13", 0, 470)]
|
|
window.close()
|
|
|
|
|
|
def test_only_usable_candidates_can_be_added(make_window):
|
|
window = make_window()
|
|
tool = window.sequence_panel.array_tool
|
|
added: list = []
|
|
tool.addRequested.connect(added.append)
|
|
tool.set_checked([Candidate(0, 0, False, "off_surface")])
|
|
assert not tool.add_button.isEnabled()
|
|
tool.set_checked([Candidate(0, 0, True), Candidate(5, 5, False, "near_edge")])
|
|
assert tool.add_button.isEnabled()
|
|
assert tool.add_button.text() == t("array.btn_add", count=1)
|
|
tool.add_button.click()
|
|
assert [c.u for c in added[0]] == [0]
|
|
window.close()
|
|
|
|
|
|
def test_adding_candidates_skips_a_point_already_in_the_sequence(make_window, monkeypatch):
|
|
window = make_window()
|
|
panel = window.sequence_panel
|
|
monkeypatch.setattr(window, "_map_origin", lambda: (100, 150))
|
|
monkeypatch.setattr(
|
|
window.finger_panel,
|
|
"solve_pixel_row",
|
|
lambda x, y: {"X": 1.0, "Y": 2.0, "Z": 3.0, "u_px": x - 100.0, "v_px": 150.0 - y},
|
|
)
|
|
before = panel.point_row_count()
|
|
window._on_array_add([Candidate(10, 20), Candidate(30, 40)]) # noqa: SLF001
|
|
window._on_array_add([Candidate(10, 20), Candidate(50, 60)]) # noqa: SLF001
|
|
assert panel.point_row_count() == before + 3
|
|
window.close()
|