2026-01-26 18:56:53 +09:00

119 lines
4.8 KiB
C#

/*
* Copyright (c) 2025 LG Electronics Inc.
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
*/
using VisionCommon;
using System;
using System.Collections.Generic;
namespace VisionAligner {
/// <summary>
/// 헤드 얼라인
/// </summary>
public class AlignModeHead : AlignMode {
private AlignModeHead() : base() {
// For UnitTest
}
/// <summary>
/// 생성자
/// </summary>
/// <param name="alignInfo">얼라인 정보</param>
public AlignModeHead(AlignInfo alignInfo) : base(alignInfo) { }
#region N-Point Align
/// <summary>
/// N-포인트 얼라인 보정량 T를 계산한다.
/// </summary>
/// <param name="meaPoints">패턴 검출 위치</param>
/// <param name="refPoints">레퍼런스(기준) 위치</param>
/// <param name="flipY">좌표계의 Y축 반전 여부</param>
/// <returns>얼라인 보정량</returns>
protected override AlignDelta CalculateT(
List<DoublePoint> meaPoints,
List<DoublePoint> refPoints,
int flipY) {
// Align Direction : refPoints -> meaPoints
// meaPoints, refPoints 순서가 반대
return AlignerImpl.CalculateT(refPoints, meaPoints, flipY);
}
/// <summary>
/// ICP 알고리즘을 이용하여 N-포인트 얼라인 보정량 T를 계산한다.
/// </summary>
/// <param name="meaPoints">패턴 검출 위치</param>
/// <param name="refPoints">레퍼런스(기준) 위치</param>
/// <param name="flipY">좌표계의 Y축 반전 여부</param>
/// <returns>얼라인 보정량</returns>
protected override AlignDelta CalculateT_ICP(
List<DoublePoint> meaPoints,
List<DoublePoint> refPoints,
int flipY) {
// Align Direction : refPoints -> meaPoints
// meaPoints, refPoints 순서가 반대
return AlignerImpl.CalculateT_ICP(refPoints, meaPoints, flipY);
}
/// <summary>
/// N-포인트 얼라인 보정량 XY를 계산한다.
/// </summary>
/// <param name="meaPoints">패턴 검출 위치</param>
/// <param name="refPoints">레퍼런스(기준) 위치</param>
/// <param name="flipY">좌표계의 Y축 반전 여부</param>
/// <param name="thetaOrigin">회전 원점</param>
/// <param name="alignT">얼라인 보정량 T</param>
/// <returns>얼라인 보정량</returns>
protected override AlignDelta CalculateXY(
List<DoublePoint> meaPoints,
List<DoublePoint> refPoints,
int flipY,
DoublePoint thetaOrigin,
Angle alignT) {
var normalizedAngle = CoordSystem.NormalizeAngleDirection(alignT, flipY);
// XY
var centroidRefPoint = DoublePoint.GetCentroid(refPoints);
var markOffsets = new List<DoublePoint>();
for (int i = 0; i < refPoints.Count; i++) {
markOffsets.Add(meaPoints[i] - refPoints[i]);
}
var centroidMarkOffset = DoublePoint.GetCentroid(markOffsets);
AlignDelta alignDeltaXY = NativeAligner.HeadAlignXY(
normalizedAngle,
centroidRefPoint - thetaOrigin, // Coordinate Origin Convert : (0, 0) -> thetaOrigin
centroidMarkOffset - thetaOrigin); // Coordinate Origin Convert : (0, 0) -> thetaOrigin
alignDeltaXY.Translation += thetaOrigin; // Coordinate Origin Convert : (0, 0) <- thetaOrigin
return new AlignDelta(
alignDeltaXY.Translation,
Angle.CreateWithDegree(0));
}
#endregion
#region 1-Point Align
/// <summary>
/// 1-포인트 얼라인 보정량 XYT를 계산한다.
/// </summary>
/// <param name="meaPoint">패턴 검출 위치</param>
/// <param name="refPoint">레퍼런스(기준) 위치</param>
/// <param name="flipY">좌표계의 Y축 반전 여부</param>
/// <param name="thetaOrigin">회전 원점</param>
/// <param name="theta">얼라인 보정량 T</param>
/// <returns>얼라인 보정량</returns>
protected override AlignDelta CalculateXYT(
DoublePoint meaPoint,
DoublePoint refPoint,
int flipY,
DoublePoint thetaOrigin,
Angle theta) {
// Align Direction : refPoint -> meaPoint
// refPoint, meaPoint 순서가 반대이다.
// theta는 패턴의 검출 각도 = 자재의 틀어짐
// -> Head 보정량 : theta 부호 반전 불필요
return AlignerImpl.CalculateXYT(refPoint, meaPoint, theta, thetaOrigin, flipY);
}
#endregion
}
}