/* * Copyright (c) 2025 LG Electronics Inc. * SPDX-License-Identifier: LicenseRef-LGE-Proprietary */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace VisionCommon { // 하드웨어 카메라 플립 유무 public enum eFlipY : int { True = -1, False = 1 } // 이미지 플립 방향 public enum eImageFlip { None, // 반전X LeftToRight, // 좌우반전 TopToBottom // 상하반전 } // 이미지 회전 각도 public enum eImageRotation { None = 0, // 회전X CW_DEG_90 = 90, // 90도 회전 CW_DEG_180 = 180, // 180도 회전 CW_DEG_270 = 270, // 270도 회전 } public enum eCoordSysType { RotX_0, RotX_90, RotX_180, RotX_270, RotX_0_FilpY, RotX_90_FilpY, RotX_180_FilpY, RotX_270_FilpY, } /// /// Source -> Target 좌표계 변환을 위환 변환 값으로 작성한다. /// public class CoordSystem : ICloneable { public Angle RotationX { get; set; } public eFlipY FlipY { get; set; } public eDirection DirectionT { get; set; } public eDirection DirectionZ { get; set; } public CoordSystem() : this(new Angle(), eFlipY.False, eDirection.Plus) { } public CoordSystem( Angle rotationX, eFlipY flipY, eDirection directionT, eDirection directionZ = eDirection.Plus) { this.RotationX = rotationX; this.FlipY = flipY; this.DirectionT = directionT; this.DirectionZ = directionZ; } public static Angle NormalizeAngleDirection(Angle angle, int flipY) { // Image Coordinate (Vision Core) -> Calibrated Coordinate return Angle.CreateWithRadian(angle.Radian * flipY); } public static Angle DenormalizeAngleDirection(Angle angle, int flipY) { // Calibrated Coordinate -> Image Coordinate (Vision Core) return Angle.CreateWithRadian(angle.Radian * flipY); } public static CoordSystem operator -(CoordSystem cs1, CoordSystem cs2) { var angleDiff = Angle.DenormalizeAngle(cs1.RotationX - cs2.RotationX); return new CoordSystem( angleDiff, (eFlipY)((int)cs1.FlipY * (int)cs2.FlipY), (eDirection)((int)cs1.DirectionT * (int)cs2.DirectionT), (eDirection)((int)cs1.DirectionZ * (int)cs2.DirectionZ)); } public static DoublePoint ApplyDirection(DoublePoint point, SetupDirection setupDirection) { return ApplyDirection( point, Angle.CreateWithDegree(setupDirection.RotationX), setupDirection.FlipY); } public static DoublePoint ApplyDirection(DoublePoint point, CoordSystem csSource, CoordSystem csTarget) { var csCorrection = csTarget - csSource; return ApplyDirection( point, csCorrection.RotationX * (int)csSource.FlipY, csCorrection.FlipY); } public static DoublePoint ApplyDirection(DoublePoint point, Angle rotationX, eFlipY flipY) { return MathUtil.RotateFlip( point, rotationX * -1, // 좌표계 변환의 회전량은 부호가 반대이다. flipY); } public static double ApplyDirectionT(double deltaT, CoordSystem coordSystem) { return ApplyDirection(deltaT, coordSystem.DirectionT); } public static double ApplyDirectionZ(double deltaZ, CoordSystem coordSystem) { return ApplyDirection(deltaZ, coordSystem.DirectionZ); } public static double ApplyDirection(double delta, eDirection direction) { return delta * (int)direction; } public static eCoordSysType ToCoordSysType(CoordSystem coordSystem) { return ToCoordSysType(coordSystem.RotationX, coordSystem.FlipY); } public static eCoordSysType ToCoordSysType(Angle rotationX, eFlipY flipY) { var flipYType = (flipY == eFlipY.False) ? eCoordSysType.RotX_0 : eCoordSysType.RotX_0_FilpY; var rotationXType = (int)(rotationX.Degree / 90); return flipYType + rotationXType; } public static CoordSystem ToCoordSystem(eCoordSysType coordSysType, eDirection directionT, eDirection directionZ = eDirection.Plus) { return new CoordSystem() { RotationX = GetRotationX(coordSysType), FlipY = GetFlipY(coordSysType), DirectionT = directionT, DirectionZ = directionZ }; } public static Angle GetRotationX(eCoordSysType coordSysType) { return Angle.CreateWithDegree((int)coordSysType % 4 * 90); } public static eFlipY GetFlipY(eCoordSysType coordSysType) { return (coordSysType < eCoordSysType.RotX_0_FilpY) ? eFlipY.False : eFlipY.True; } public object XFlip() { return XFlip(new CoordSystem(RotationX.Clone() as Angle, FlipY, DirectionT, DirectionZ)); } public static CoordSystem XFlip(CoordSystem coordSystem) { return new CoordSystem() { RotationX = Angle.CreateWithDegree(coordSystem.RotationX.Degree + 180), FlipY = (eFlipY)((int)coordSystem.FlipY * -1), DirectionT = coordSystem.DirectionT, DirectionZ = coordSystem.DirectionZ }; } public object YFlip() { return YFlip(new CoordSystem(RotationX.Clone() as Angle, FlipY, DirectionT, DirectionZ)); } public static CoordSystem YFlip(CoordSystem coordSystem) { return new CoordSystem() { RotationX = coordSystem.RotationX.Clone() as Angle, FlipY = (eFlipY)((int)coordSystem.FlipY * -1), DirectionT = coordSystem.DirectionT, DirectionZ = coordSystem.DirectionZ }; } public override bool Equals(object obj) { CoordSystem cs = obj as CoordSystem; if (cs == null || this.GetType() != cs.GetType()) { return false; } return this.RotationX.Equals(cs.RotationX) && (this.FlipY == cs.FlipY) && (this.DirectionT == cs.DirectionT) && (this.DirectionZ == cs.DirectionZ); } public override int GetHashCode() { return RotationX.GetHashCode() ^ FlipY.GetHashCode() ^ DirectionT.GetHashCode() ^ DirectionZ.GetHashCode(); } public object Clone() { return new CoordSystem(RotationX.Clone() as Angle, FlipY, DirectionT, DirectionZ); } public override string ToString() { return $"RotX : {RotationX}, FlipY : {FlipY}, DirT : {DirectionT}, DirZ : {DirectionZ}"; } } }