/* * Copyright (c) 2025 LG Electronics Inc. * SPDX-License-Identifier: LicenseRef-LGE-Proprietary */ using VisionCommon; using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace VisionCalibrator { /// 한 점의 좌표 정보 public struct PointData { /// X 좌표 public double X; /// Y 좌표 public double Y; } /// 여러 점들의 좌표 정보 public struct PointsData { /// 점들의 수 public int Count; /// 점들의 좌표 정보 public IntPtr Points; } /// 회전을 위한 정보 public struct CircleData { /// 회전 원점의 좌표 public PointData Center; /// 회전 각도 public double Radius; /// 반지름 길이 public double Rms; } internal static class NativeCalibrator { private const string FILE_NAME_VISION_DLL = "VisionCore.dll"; [DllImport(FILE_NAME_VISION_DLL)] extern internal static double GetAxisRadian(ref PointsData meaPoints); [DllImport(FILE_NAME_VISION_DLL)] extern internal static CircleData CircleFit(ref PointsData meaPoints, double rotationRadian); [DllImport(FILE_NAME_VISION_DLL)] extern internal static PointData TransformImageToStatic(PointData fovCenter, PointData fovCenterOffset, double setupDirection, double errorRotation, int imageWidth, int imageHeight, int flipY, double pixelSizeX, double pixelSizeY, PointData imagePoint); [DllImport(FILE_NAME_VISION_DLL)] extern internal static PointData TransformStaticToImage(PointData fovCenter, PointData fovCenterOffset, double setupDirection, double errorRotation, int imageWidth, int imageHeight, int flipY, double pixelSizeX, double pixelSizeY, PointData staticPoint); [DllImport(FILE_NAME_VISION_DLL)] extern internal static double GetPixelSize2(ref PointsData meaPoints, double moveLength, double AxisAngle, char target); [DllImport(FILE_NAME_VISION_DLL)] extern internal static PointData CalcCoordConvert( double X, double Y, double markSizeX, double markSizeY, PointData llMotion, PointData hlMotion, PointData lhMotion, PointData hhMotion, double sourceRotXRad, int sourceFlipY, double targetRotXRad, int targetFlipY); [DllImport(FILE_NAME_VISION_DLL)] extern internal static PointData CalcCoordConvertInverse( double X, double Y, PointData s1, PointData s2, PointData s3, PointData s4, PointData m1, PointData m2, PointData m3, PointData m4); internal static StaticPoint StaticCalibrateThetaOrigin( List meaPoints, Angle rotation) { var mPoints = ConvertPointsData(meaPoints); CircleData result = CircleFit(ref mPoints, rotation.Radian); return new StaticPoint(result.Center.X, result.Center.Y); } private static PointsData ConvertPointsData(List points) { var pointsData = new PointsData(); pointsData.Count = points.Count; pointsData.Points = Marshal.AllocHGlobal(Marshal.SizeOf() * pointsData.Count); try { for (int i = 0; i < pointsData.Count; i++) { var pointData = new PointData() { X = points[i].X, Y = points[i].Y }; // PointData Marshaling IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(pointData)); Marshal.StructureToPtr(pointData, ptr, false); // Copy PointData to Array Marshal.StructureToPtr(ptr, (IntPtr)((long)pointsData.Points + Marshal.SizeOf() * i), false); } } catch (Exception e) { } return pointsData; } private static PointsData ConvertPointsData(List points) { var pointsData = new PointsData(); pointsData.Count = points.Count; pointsData.Points = Marshal.AllocHGlobal(Marshal.SizeOf() * pointsData.Count); try { for (int i = 0; i < pointsData.Count; i++) { var pointData = new PointData() { X = points[i].X, Y = points[i].Y }; // PointData Marshaling IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(pointData)); Marshal.StructureToPtr(pointData, ptr, false); // Copy PointData to Array Marshal.StructureToPtr(ptr, (IntPtr)((long)pointsData.Points + Marshal.SizeOf() * i), false); } } catch (Exception e) { } return pointsData; } internal static StaticPoint ImageToStatic( PointData fovCenter, PointData fovCenterOffset, double setupDirection, double errorRotation, int imageWidth, int imageHeight, int flipY, double pixelSizeX, double pixelSizeY, PointData imagePoint) { var pointData = new PointData(); try { pointData = TransformImageToStatic( fovCenter, fovCenterOffset, setupDirection, errorRotation, imageWidth, imageHeight, flipY, pixelSizeX, pixelSizeY, imagePoint); } catch (Exception e) { } return new StaticPoint(pointData.X, pointData.Y); } internal static ImagePoint StaticToImage( PointData fovCenter, PointData fovCenterOffset, double setupDirection, double errorRotation, int imageWidth, int imageHeight, int flipY, double pixelSizeX, double pixelSizeY, PointData staticPoint) { var pointData = new PointData(); try { pointData = TransformStaticToImage( fovCenter, fovCenterOffset, setupDirection, errorRotation, imageWidth, imageHeight, flipY, pixelSizeX, pixelSizeY, staticPoint); } catch (Exception e) { } return new ImagePoint(pointData.X, pointData.Y); } internal static double CalibrateImagePixel(List meaPoints, double moveLength, double AxisAngle, char target) { var mPoints = ConvertPointsData(meaPoints); double pixelSize = GetPixelSize2(ref mPoints, moveLength, AxisAngle, target); return pixelSize; } internal static Angle StaticCalibrateErrorRot( List meaPoints) { var mPoints = ConvertPointsData(meaPoints); double axisRadian = GetAxisRadian(ref mPoints); return Angle.CreateWithRadian(axisRadian); } internal static MotionPoint CoordConveter( double X, double Y, double MarkSizeX, double MarkSizeY, PointData llMotion, PointData hlMotion, PointData lhMotion, PointData hhMotion, double sourceRotXRad, int sourceFlipY, double targetRotXRad, int targetFlipY) { var pointData = new PointData(); try { pointData = CalcCoordConvert( X, Y, MarkSizeX, MarkSizeY, llMotion, hlMotion, lhMotion, hhMotion, sourceRotXRad, sourceFlipY, targetRotXRad, targetFlipY); } catch (Exception e) { } return new MotionPoint(pointData.X, pointData.Y); } internal static StaticPoint CoordConvertInverse( double X, double Y, PointData s1, PointData s2, PointData s3, PointData s4, PointData m1, PointData m2, PointData m3, PointData m4) { var pointData = new PointData(); try { pointData = CalcCoordConvertInverse( X, Y, s1, s2, s3, s4, m1, m2, m3, m4); } catch (Exception e) { } return new StaticPoint(pointData.X, pointData.Y); } } }