정렬 스냅 자체는 있었다. 다만 축마다 선 하나만, 그것도 화면 끝에서 끝까지 긋는 무한 점선이라 무엇에 맞춘 것인지가 안 보였다. 판단을 SheetMe.Core 로 옮기고 후보의 출처를 끝까지 들고 간다. 왜 옮겼나. 스냅은 눈으로만 확인되는 종류의 코드다 — 후보 하나, 열거 순서 하나가 바뀌면 붙는 자리가 조용히 달라지고 드래그해 보기 전엔 아무도 모른다. Core/Layout 의 SnapSolver 는 순수 기하이고 단위 테스트 27건이 승자 규칙·가이드 개수·선분 범위·간격 계산을 못 박는다. SnapEngine 에는 "어떤 사각형이 후보인가"와 좌표 변환만 남았다. 달라진 것들: · 동시에 맞는 정렬은 전부 보인다. 폭이 같은 형제 옆에 대면 좌·중·우 세 줄이 함께 뜬다. 보정량은 승자 하나만 쓰되, 그 보정을 적용했을 때 실제로 맞는 후보만 선으로 낸다 — |거리|만 같고 부호가 반대인 후보까지 그리면 '붙었다고 그려 놓고 안 붙은' 선이 된다. · 선이 선분이 됐다. 형제 가이드는 관련된 것들의 합집합 범위까지만, 용지 가이드는 그 용지 전체. 같은 좌표의 형제 여럿은 한 선으로 합치고 범위만 넓힌다. 덤으로 대비 문제도 풀렸다 — 예전 분홍(#FF4FA3)은 종이 밖 회색 배경 위에서 2.1:1 로 죽었다. · 허용 오차가 화면 기준이 됐다. 월드 고정이면 줌 50%에서 두 배로 끈적이고 200%에서 절반으로 미끄러진다 — 손끝 감각은 화면 거리로 정해진다. 핸들 히트 반경도 같은 병이라 함께 고쳤다 (줌 300%에서 그림은 8px 인데 판정이 18px 였다). 선 두께도 화면 1px 로 고정한다. · 승자가 결정적이 됐다. 예전에는 컨트롤 열거 순서가 동률을 갈랐다. 이제 |거리| → 종류(형제 모서리 > 형제 중심 > 용지 경계 > 용지 중앙) → 좌표 → 모서리 순이다. · 간격 균등. 형제들이 이미 같은 간격으로 늘어서 있으면 그 리듬에 끼거나 이어 붙는 자리에 붙고, 같은 값이 된 빈틈 전부에 막대와 수치 칩을 놓는다. 양옆만 재면 "30"이 한 번 뜰 뿐이라 무엇과 같아졌는지 안 보인다. 같은 축에서 정렬과 동시에 사정권이면 정렬이 이긴다 — 거리로 겨루게 하면 한 픽셀 차이로 표시가 선↔막대로 튀어 종잡을 수 없다. · 후보 범위. 컨테이너 자식도 이제 후보다(히트테스트는 재귀하는데 스냅만 최상위를 보던 규칙 불일치). 대신 끌려가는 컨테이너의 자식은 빼야 한다 — 선택 목록엔 없지만 함께 움직이므로 빼지 않으면 컨테이너가 제 자식에게 붙어 그 자리에서 굳는다. · 리사이즈. 후보를 이동 드래그에서만 모으고 있어서, 앱을 켜자마자 핸들을 잡으면 스냅이 없고 이동을 한 번 한 뒤에는 그때의 낡은 좌표에 붙었다. 리사이즈 시작에도 모으고 놓을 때 버린다. 모서리 스냅이 '첫 매치'였던 것도 이동과 같은 최근접 규칙으로 통일했다. 가이드도 함께 보인다. · 정합된 축은 반올림하지 않는다. 형제 폭이 홀수면 중심이 반정수라, 반올림하면 중앙에 맞췄는데 0.5px 어긋난 채로 놓인다. 무한선일 땐 안 보였지만 선분이 되면 모서리에서 뜬 게 눈에 띈다. 저장은 LegacyFormat.FormatPair 가 어차피 정수로 쓰므로 포맷은 영향 없다. 성능 가드: 한 줄에 겹치는 형제가 64개 넘으면 간격 계산을 건너뛰고(정렬은 정상), 형제가 2000개 넘으면 간격을 끈다. 후보 정렬은 드래그 시작에 1회, 프레임 경로는 무할당. 가이드 내용이 이전과 같으면 컬렉션을 건드리지 않는다. 신규 진단 --snap-shots — 종이와 오버레이를 겹쳐 드래그 도중을 찍는다. 기존 --render-smoke/--db-render 는 종이만 찍어 오버레이가 안 나왔다. 선이 어디서 어디까지 그어지는지, 몇 개가 동시에 보이는지는 그림으로만 확인된다. 게이트는 함께 남기는 _report.txt 의 수치로 걸고 PNG 는 눈 검증 보조다(픽셀 비교는 테마·글꼴에 흔들려 게이트로 못 쓴다). 게이트: 테스트 257/257(신규 27), --edit-smoke 223건 0실패(스냅 검사 14건 신규), --query-popup 17/17, --maxrect 10/10, --db-smoke 3000 diff 0·예외 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일, --snap-shots 7종 0실패. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
374 lines
16 KiB
C#
374 lines
16 KiB
C#
using SheetMe.Core.Layout;
|
||
|
||
namespace SheetMe.Core.Tests;
|
||
|
||
/// <summary>
|
||
/// 스냅 계산 고정 — 손에 닿는 감각을 숫자로 못 박는다.
|
||
///
|
||
/// 스냅은 "어쩐지 잘 붙는다"로는 지킬 수 없다. 후보가 하나 늘거나 열거 순서가 바뀌는 것만으로
|
||
/// 붙는 자리가 조용히 달라지고, 그건 드래그해 보기 전엔 아무도 모른다.
|
||
/// 그래서 승자 규칙·가이드 개수·선분 범위·간격 균등을 전부 여기서 고정한다.
|
||
/// </summary>
|
||
[TestClass]
|
||
public sealed class SnapSolverTests
|
||
{
|
||
#region Member Fields
|
||
private static readonly SnapRect Page = new(0, 0, 720, 856);
|
||
private static readonly SnapOptions Options = new(Tolerance: 6, GridSize: 4, EnableSpacing: true);
|
||
private static readonly SnapOptions NoSpacing = Options with { EnableSpacing = false };
|
||
#endregion
|
||
|
||
#region Methods
|
||
private static SnapSolver Solver(params SnapRect[] siblings)
|
||
{
|
||
var solver = new SnapSolver();
|
||
solver.Prepare(new SnapContext
|
||
{
|
||
Pages = new[] { Page },
|
||
Siblings = siblings,
|
||
SpacingPage = Page,
|
||
});
|
||
return solver;
|
||
}
|
||
|
||
// ── 정렬 ───────────────────────────────────────────────────────────
|
||
|
||
[TestMethod]
|
||
public void 형제_좌변에_붙는다()
|
||
{
|
||
// 형제 폭을 81 로 잡아 중심(140.5)이 이동체 우변(137)과 '같은 거리'가 되지 않게 한다 —
|
||
// 80 이면 중심이 140 이라 우변도 정확히 +3 이 되어 가이드가 둘 나온다(그건 그것대로 옳다)
|
||
var solver = Solver(new SnapRect(100, 50, 81, 20));
|
||
var result = solver.SolveMove(new SnapRect(0, 200, 40, 10), 97, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(100, 0 + result.Dx, 1e-9, "좌변이 형제 좌변에 맞아야 한다");
|
||
Assert.AreEqual(1, result.Guides.Count);
|
||
var guide = result.Guides[0];
|
||
Assert.IsTrue(guide.IsVertical);
|
||
Assert.AreEqual(100, guide.Position, 1e-9);
|
||
Assert.AreEqual(SnapGuideKind.SiblingEdge, guide.Kind);
|
||
// 선분은 형제와 이동체를 모두 덮는 만큼만 — 화면을 가로지르지 않는다
|
||
Assert.AreEqual(50, guide.Start, 1e-9);
|
||
Assert.AreEqual(210, guide.End, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 허용오차_경계는_포함이고_그_바깥은_격자로_떨어진다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 50, 80, 20));
|
||
|
||
var onEdge = solver.SolveMove(new SnapRect(0, 200, 40, 10), 94, 0, NoSpacing, free: false);
|
||
Assert.IsTrue(onEdge.SnappedX, "거리 6은 붙는다");
|
||
|
||
var justOutside = solver.SolveMove(new SnapRect(0, 200, 40, 10), 93.999, 0, NoSpacing, free: false);
|
||
Assert.IsFalse(justOutside.SnappedX, "거리 6.001 은 안 붙는다");
|
||
Assert.AreEqual(0, result4(justOutside.Dx) % 4, "정합 실패 축은 4px 격자");
|
||
Assert.AreEqual(0, justOutside.Guides.Count);
|
||
|
||
static double result4(double dx) => Math.Round(dx, 6);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 같은_좌표의_형제_둘은_가이드_하나로_합쳐지고_범위가_넓어진다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 0, 50, 20), new SnapRect(100, 300, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(0, 200, 40, 10), 97, 0, NoSpacing, free: false);
|
||
|
||
Assert.AreEqual(1, result.Guides.Count, "같은 자리에 선을 겹쳐 긋지 않는다");
|
||
Assert.AreEqual(0, result.Guides[0].Start, 1e-9);
|
||
Assert.AreEqual(320, result.Guides[0].End, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 서로_다른_자리에_동시에_맞으면_가이드가_둘이다()
|
||
{
|
||
// 이동체 폭 40. Left=100 에 형제 A 의 좌변, Right=140 에 형제 B 의 좌변
|
||
var solver = Solver(new SnapRect(100, 0, 50, 20), new SnapRect(140, 400, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(0, 200, 40, 10), 97, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(2, result.Guides.Count);
|
||
CollectionAssert.AreEquivalent(
|
||
new[] { 100.0, 140.0 },
|
||
result.Guides.Select(g => g.Position).ToArray());
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 거리가_같아도_부호가_반대면_한쪽만_그린다()
|
||
{
|
||
// 이동 후 Left=100 기준: 형제 A 좌변 103(+3), 형제 B 좌변 97(−3).
|
||
// 형제를 넓게 잡아 중심·우변이 사정권에 안 들어오게 한다(들어오면 더 가까운 매치가 승자가 된다)
|
||
var solver = Solver(new SnapRect(103, 0, 200, 20), new SnapRect(97, 400, 200, 20));
|
||
var result = solver.SolveMove(new SnapRect(0, 200, 40, 10), 100, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(1, result.Guides.Count,
|
||
"보정 후 실제로 맞는 것만 그린다 — 반대편에 선을 그으면 '붙었다고 그려 놓고 안 붙은' 선이 된다");
|
||
Assert.AreEqual(97, result.Guides[0].Position, 1e-9, "동률이면 좌표가 작은 쪽이 이긴다");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 중심_정합은_반정수를_보존한다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 0, 81, 20)); // CenterX = 140.5
|
||
var result = solver.SolveMove(new SnapRect(0, 200, 40, 10), 120, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(120.5, 0 + result.Dx, 1e-9, "반올림하면 중심이 0.5px 어긋난다");
|
||
Assert.AreEqual(SnapGuideKind.SiblingCenter, result.Guides[0].Kind);
|
||
Assert.AreEqual(140.5, result.Guides[0].Position, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 용지_가이드는_용지_전체로_긋는다()
|
||
{
|
||
var solver = Solver();
|
||
var result = solver.SolveMove(new SnapRect(3, 200, 40, 10), 0, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(SnapGuideKind.PageEdge, result.Guides[0].Kind);
|
||
Assert.AreEqual(0, result.Guides[0].Start, 1e-9);
|
||
Assert.AreEqual(856, result.Guides[0].End, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 용지_중앙에_붙는다()
|
||
{
|
||
var solver = Solver();
|
||
// 폭 40 이 용지 중앙(360)에 오려면 Left=340
|
||
var result = solver.SolveMove(new SnapRect(337, 200, 40, 10), 0, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(340, 337 + result.Dx, 1e-9);
|
||
Assert.AreEqual(SnapGuideKind.PageCenter, result.Guides[0].Kind);
|
||
Assert.AreEqual(360, result.Guides[0].Position, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 후보가_없으면_격자로_떨어지고_가이드는_없다()
|
||
{
|
||
var solver = Solver(new SnapRect(500, 500, 20, 20));
|
||
var result = solver.SolveMove(new SnapRect(101, 200, 40, 10), 0, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsFalse(result.SnappedX);
|
||
Assert.AreEqual(100, 101 + result.Dx, 1e-9);
|
||
Assert.AreEqual(0, result.Guides.Count);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 형제_모서리가_용지_중앙보다_이긴다()
|
||
{
|
||
// 이동체 Left=337 → 형제 좌변 340 이 +3, 중심 357 → 용지 중앙 360 도 +3.
|
||
// 둘 다 실제로 맞으므로 선은 둘 다 그린다 — 갈리는 것은 '어느 쪽으로 보정하는가'다.
|
||
var solver = Solver(new SnapRect(340, 0, 200, 20));
|
||
var result = solver.SolveMove(new SnapRect(337, 200, 40, 10), 0, 0, NoSpacing, free: false);
|
||
|
||
Assert.AreEqual(340, 337 + result.Dx, 1e-9, "거리가 같으면 형제 모서리가 용지 중앙보다 이긴다");
|
||
Assert.AreEqual(2, result.Guides.Count);
|
||
Assert.IsTrue(result.Guides.Any(g => g.Kind == SnapGuideKind.SiblingEdge));
|
||
Assert.IsTrue(result.Guides.Any(g => g.Kind == SnapGuideKind.PageCenter));
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 한_축만_붙어도_다른_축은_격자로_간다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 0, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(97, 201, 40, 10), 0, 0, NoSpacing, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.IsFalse(result.SnappedY);
|
||
Assert.AreEqual(200, 201 + result.Dy, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void Alt_는_격자까지_전부_끈다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 50, 80, 20));
|
||
var result = solver.SolveMove(new SnapRect(0, 200, 40, 10), 97.3, 11.7, Options, free: true);
|
||
|
||
Assert.AreEqual(97.3, result.Dx, 1e-9);
|
||
Assert.AreEqual(11.7, result.Dy, 1e-9);
|
||
Assert.IsFalse(result.SnappedX);
|
||
Assert.AreEqual(0, result.Guides.Count);
|
||
Assert.AreEqual(0, result.Spacings.Count);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 같은_입력을_두_번_풀어도_결과가_같다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 0, 50, 20), new SnapRect(140, 400, 50, 20));
|
||
var first = solver.SolveMove(new SnapRect(0, 200, 40, 10), 97, 0, Options, free: false);
|
||
var second = solver.SolveMove(new SnapRect(0, 200, 40, 10), 97, 0, Options, free: false);
|
||
|
||
Assert.AreEqual(first.Dx, second.Dx, 1e-9);
|
||
Assert.AreEqual(first.Guides.Count, second.Guides.Count, "스크래치 버퍼가 새면 두 번째가 불어난다");
|
||
Assert.AreEqual(first.Spacings.Count, second.Spacings.Count);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 페이지가_멀리_떨어져_있어도_정밀도가_유지된다()
|
||
{
|
||
var solver = new SnapSolver();
|
||
solver.Prepare(new SnapContext
|
||
{
|
||
Pages = new[] { new SnapRect(0, 10000, 720, 856) },
|
||
Siblings = new[] { new SnapRect(100, 10050, 80, 20) },
|
||
});
|
||
var result = solver.SolveMove(new SnapRect(0, 10200, 40, 10), 97, 0, NoSpacing, free: false);
|
||
|
||
Assert.AreEqual(100, 0 + result.Dx, 1e-9);
|
||
}
|
||
|
||
// ── 간격 균등 ──────────────────────────────────────────────────────
|
||
|
||
[TestMethod]
|
||
public void 두_형제_사이에_끼면_남는_틈을_반씩_나눈다()
|
||
{
|
||
// 틈 [50,200] = 150, 이동 폭 40 → 양쪽 55 씩 → Left = 105
|
||
var solver = Solver(new SnapRect(0, 0, 50, 20), new SnapRect(200, 0, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(103, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(105, 103 + result.Dx, 1e-9);
|
||
Assert.AreEqual(2, result.Spacings.Count);
|
||
Assert.AreEqual(55, result.Spacings[0].Gap, 1e-9);
|
||
Assert.AreEqual(55, result.Spacings[1].Gap, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 줄_뒤에_같은_간격으로_이어_붙는다()
|
||
{
|
||
// 간격 30 (50→80). 뒤에 붙으면 Left = 130 + 30 = 160
|
||
var solver = Solver(new SnapRect(0, 0, 50, 20), new SnapRect(80, 0, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(157, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(160, 157 + result.Dx, 1e-9);
|
||
Assert.AreEqual(30, result.Spacings[^1].Gap, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 줄_앞에_같은_간격으로_이어_붙는다()
|
||
{
|
||
// 간격 30 (150→180). 앞에 붙으면 Left = 100 − 30 − 40 = 30
|
||
var solver = Solver(new SnapRect(100, 0, 50, 20), new SnapRect(180, 0, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(33, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(30, 33 + result.Dx, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 교차축이_안_겹치면_같은_줄이_아니다()
|
||
{
|
||
var solver = Solver(new SnapRect(0, 500, 50, 20), new SnapRect(80, 500, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(157, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.AreEqual(0, result.Spacings.Count);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 형제가_하나면_간격_후보가_없다()
|
||
{
|
||
var solver = Solver(new SnapRect(0, 0, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(300, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.AreEqual(0, result.Spacings.Count);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 정렬이_되면_간격은_보지_않는다()
|
||
{
|
||
// 뒤에 붙는 자리(160)와 형제 좌변 정합(158)이 둘 다 사정권
|
||
var solver = Solver(new SnapRect(0, 0, 50, 20), new SnapRect(80, 0, 50, 20), new SnapRect(158, 300, 20, 20));
|
||
var result = solver.SolveMove(new SnapRect(157, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.IsTrue(result.SnappedX);
|
||
Assert.AreEqual(158, 157 + result.Dx, 1e-9, "정렬이 이긴다");
|
||
Assert.AreEqual(0, result.Spacings.Count);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 용지_밖으로_나가는_간격_자리는_버린다()
|
||
{
|
||
// 앞에 붙는 자리가 음수가 되는 배치
|
||
var solver = Solver(new SnapRect(10, 0, 50, 20), new SnapRect(90, 0, 50, 20));
|
||
var result = solver.SolveMove(new SnapRect(-58, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.AreEqual(0, result.Spacings.Count);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 겹치는_형제가_너무_많으면_간격을_포기하고_정렬만_한다()
|
||
{
|
||
var many = new SnapRect[70];
|
||
for (var i = 0; i < many.Length; i++)
|
||
{
|
||
many[i] = new SnapRect(i * 60, 0, 50, 20);
|
||
}
|
||
var solver = Solver(many);
|
||
var result = solver.SolveMove(new SnapRect(58, 0, 40, 20), 0, 0, Options, free: false);
|
||
|
||
Assert.AreEqual(0, result.Spacings.Count, "성능 가드");
|
||
Assert.IsTrue(result.SnappedX, "정렬 스냅은 그대로 돈다");
|
||
}
|
||
|
||
// ── 리사이즈 · 줌 ──────────────────────────────────────────────────
|
||
|
||
[TestMethod]
|
||
public void 모서리_스냅은_첫_매치가_아니라_최근접이다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 0, 0, 20), new SnapRect(104, 0, 0, 20));
|
||
var result = solver.SolveEdge(102.5, isXAxis: true, Options, free: false);
|
||
|
||
Assert.IsTrue(result.Snapped);
|
||
Assert.AreEqual(104, result.Value, 1e-9, "이동 스냅과 같은 규칙이어야 한다");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 모서리_후보가_없으면_격자로_떨어진다()
|
||
{
|
||
var solver = Solver(new SnapRect(500, 0, 10, 20));
|
||
var result = solver.SolveEdge(102, isXAxis: true, Options, free: false);
|
||
|
||
Assert.IsFalse(result.Snapped);
|
||
Assert.AreEqual(104, result.Value, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 모서리_스냅도_Alt_로_꺼진다()
|
||
{
|
||
var solver = Solver(new SnapRect(100, 0, 0, 20));
|
||
var result = solver.SolveEdge(102.5, isXAxis: true, Options, free: true);
|
||
|
||
Assert.IsFalse(result.Snapped);
|
||
Assert.AreEqual(102.5, result.Value, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 허용오차는_화면_기준이라_줌에_반비례한다()
|
||
{
|
||
Assert.AreEqual(3, SnapOptions.ForZoom(6, 4, 2.0, true).Tolerance, 1e-9);
|
||
Assert.AreEqual(12, SnapOptions.ForZoom(6, 4, 0.5, true).Tolerance, 1e-9);
|
||
Assert.AreEqual(6, SnapOptions.ForZoom(6, 4, 1.0, true).Tolerance, 1e-9);
|
||
// 범위 밖 줌이 들어와도 오차가 폭주하지 않는다
|
||
Assert.AreEqual(24, SnapOptions.ForZoom(6, 4, 0.01, true).Tolerance, 1e-9);
|
||
Assert.AreEqual(2, SnapOptions.ForZoom(6, 4, 99, true).Tolerance, 1e-9);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void 같은_거리라도_줌에_따라_붙고_안_붙는다()
|
||
{
|
||
var solver = Solver(new SnapRect(104, 0, 50, 20));
|
||
var bbox = new SnapRect(100, 200, 40, 10);
|
||
|
||
var zoomedIn = solver.SolveMove(bbox, 0, 0, SnapOptions.ForZoom(6, 4, 2.0, false), free: false);
|
||
Assert.IsFalse(zoomedIn.SnappedX, "줌 200% 에서 허용오차는 3 — 거리 4는 안 붙는다");
|
||
|
||
var zoomedOut = solver.SolveMove(bbox, 0, 0, SnapOptions.ForZoom(6, 4, 0.5, false), free: false);
|
||
Assert.IsTrue(zoomedOut.SnappedX, "줌 50% 에서 허용오차는 12 — 붙는다");
|
||
}
|
||
#endregion
|
||
}
|