添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,323 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.Common.Display.Models;
|
||||
using MainShell.Log;
|
||||
using MainShell.Motion;
|
||||
using Maxwell.SemiFramework.DefaultConfig.Vision;
|
||||
using MwFramework.Controls.Components;
|
||||
using MwFramework.Controls.ControlCanvas.Model;
|
||||
using MwFramework.Controls.UIControl;
|
||||
using MwFramework.Device;
|
||||
using MwFramework.ManagerService;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace MainShell.Common.Display.ViewModel
|
||||
{
|
||||
public class CameraAxisViewModel : Screen
|
||||
{
|
||||
private const double DefaultFovX = 14.1 * 10;
|
||||
private const double DefaultFovY = 10.3 * 10;
|
||||
private const string SafeAxisMotionNotInjectedMessage = "SafeAxisMotion is not injected.";
|
||||
|
||||
private readonly object _moveLock = new object();
|
||||
|
||||
private CameraAxisDevices _cameraAxisDevices = new CameraAxisDevices();
|
||||
private double _xPixelPos;
|
||||
private double _yPixelPos;
|
||||
private double _cameraXIndex;
|
||||
private double _cameraYIndex;
|
||||
private GetConvertValue _convertFunXDelegate;
|
||||
private GetConvertValue _convertFunYDelegate;
|
||||
private ObservableCollection<PrimShape> _regions = new ObservableCollection<PrimShape>();
|
||||
private bool _isCameraEnable = true;
|
||||
private Visibility _controlVisibility = Visibility.Visible;
|
||||
private bool _isOpen;
|
||||
|
||||
[Inject]
|
||||
public SafeAxisMotion SafeAxisMotion { get; set; }
|
||||
|
||||
public CameraAxisViewModel()
|
||||
{
|
||||
ConvertFunXDelegate = new GetConvertValue(ConvertFunX);
|
||||
ConvertFunYDelegate = new GetConvertValue(ConvertFunY);
|
||||
OnLeftMouseDownCommand = new DelegateCommand<object>(OnLeftMouseDown);
|
||||
}
|
||||
|
||||
public CameraAxisDevices CameraAxisDevices
|
||||
{
|
||||
get { return _cameraAxisDevices; }
|
||||
set { SetAndNotify(ref _cameraAxisDevices, value); }
|
||||
}
|
||||
|
||||
public double XPixelPos
|
||||
{
|
||||
get { return _xPixelPos; }
|
||||
set { SetAndNotify(ref _xPixelPos, value); }
|
||||
}
|
||||
|
||||
public double YPixelPos
|
||||
{
|
||||
get { return _yPixelPos; }
|
||||
set { SetAndNotify(ref _yPixelPos, value); }
|
||||
}
|
||||
|
||||
public double CameraXIndex
|
||||
{
|
||||
get { return _cameraXIndex; }
|
||||
set { SetAndNotify(ref _cameraXIndex, value); }
|
||||
}
|
||||
|
||||
public double CameraYIndex
|
||||
{
|
||||
get { return _cameraYIndex; }
|
||||
set { SetAndNotify(ref _cameraYIndex, value); }
|
||||
}
|
||||
|
||||
public GetConvertValue ConvertFunXDelegate
|
||||
{
|
||||
get { return _convertFunXDelegate; }
|
||||
set { SetAndNotify(ref _convertFunXDelegate, value); }
|
||||
}
|
||||
|
||||
public GetConvertValue ConvertFunYDelegate
|
||||
{
|
||||
get { return _convertFunYDelegate; }
|
||||
set { SetAndNotify(ref _convertFunYDelegate, value); }
|
||||
}
|
||||
|
||||
public ObservableCollection<PrimShape> Regions
|
||||
{
|
||||
get { return _regions; }
|
||||
set { SetAndNotify(ref _regions, value); }
|
||||
}
|
||||
|
||||
public bool IsCameraEnable
|
||||
{
|
||||
get { return _isCameraEnable; }
|
||||
set { SetAndNotify(ref _isCameraEnable, value); }
|
||||
}
|
||||
|
||||
public Visibility ControlVisibility
|
||||
{
|
||||
get { return _controlVisibility; }
|
||||
set { SetAndNotify(ref _controlVisibility, value); }
|
||||
}
|
||||
|
||||
public ICommand OnLeftMouseDownCommand { get; private set; }
|
||||
|
||||
public bool IsOpen
|
||||
{
|
||||
get { return _isOpen; }
|
||||
set { SetAndNotify(ref _isOpen, value); }
|
||||
}
|
||||
|
||||
public void OnLeftMouseDown(object sender)
|
||||
{
|
||||
try
|
||||
{
|
||||
HardwareDevice selectedDevice;
|
||||
if (!TryGetSelectedDevice(out selectedDevice))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CameraAxisControlA controlA = sender as CameraAxisControlA;
|
||||
if (controlA == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Point pixelPos = new Point(controlA.YPixPos, controlA.XPixPos);
|
||||
Task.Run(() => MoveToPixelPoint(selectedDevice, pixelPos, false));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.LogSysError(ex);
|
||||
ShowOperationFailed(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void MovePosAction()
|
||||
{
|
||||
try
|
||||
{
|
||||
HardwareDevice selectedDevice;
|
||||
if (!TryGetSelectedDevice(out selectedDevice))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Point pixelPos = new Point(YPixelPos, XPixelPos);
|
||||
Task.Run(() => MoveToPixelPoint(selectedDevice, pixelPos, true));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.LogSysError(ex);
|
||||
ShowOperationFailed(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public double ConvertFunX(double interval)
|
||||
{
|
||||
try
|
||||
{
|
||||
HardwareDevice selectedDevice;
|
||||
if (!TryGetSelectedDevice(out selectedDevice))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
string name = selectedDevice.Camera.Id;
|
||||
double dx;
|
||||
double dy;
|
||||
VisionProcess.Instance.GetCameraResolution(name, out dx, out dy);
|
||||
double pixelX = interval / Math.Abs(dx);
|
||||
return pixelX;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.LogSysError(ex);
|
||||
ShowOperationFailed(ex.Message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public double ConvertFunY(double interval)
|
||||
{
|
||||
try
|
||||
{
|
||||
HardwareDevice selectedDevice;
|
||||
if (!TryGetSelectedDevice(out selectedDevice))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
string name = selectedDevice.Camera.Id;
|
||||
double dx;
|
||||
double dy;
|
||||
VisionProcess.Instance.GetCameraResolution(name, out dx, out dy);
|
||||
double pixelY = interval / Math.Abs(dy);
|
||||
return pixelY;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.LogSysError(ex);
|
||||
ShowOperationFailed(ex.Message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetSelectedDevice(out HardwareDevice selectedDevice)
|
||||
{
|
||||
selectedDevice = CameraAxisDevices != null ? CameraAxisDevices.SelectedHardwareDevice : null;
|
||||
if (!IsOpen || selectedDevice == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedDevice.Camera == null || selectedDevice.Camera.Camera == null)
|
||||
{
|
||||
ShowDeviceNotInitialized();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!selectedDevice.Camera.Camera.IsGrabbing)
|
||||
{
|
||||
LocalizedMessageBox.Show(MessageKey.VisionCameraNotGrabbing, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedDevice.AxisX == null || selectedDevice.AxisY == null)
|
||||
{
|
||||
ShowDeviceNotInitialized();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void MoveToPixelPoint(HardwareDevice selectedDevice, Point pixelPos, bool requireConfirmation)
|
||||
{
|
||||
lock (_moveLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
IAxis axisX = selectedDevice.AxisX;
|
||||
IAxis axisY = selectedDevice.AxisY;
|
||||
Point rulerPos = new Point(axisX.State.ActualPos, axisY.State.ActualPos);
|
||||
Point newRulerPoint = Algorithm.Instance.MoveToPixelPoint(selectedDevice.Camera.Id, rulerPos, pixelPos);
|
||||
|
||||
if (requireConfirmation)
|
||||
{
|
||||
double dx = newRulerPoint.X - rulerPos.X;
|
||||
double dy = newRulerPoint.Y - rulerPos.Y;
|
||||
if (!ValidateMoveRange(dx, dy))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ConfirmMove(newRulerPoint))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (SafeAxisMotion == null)
|
||||
{
|
||||
InvalidOperationException exception = new InvalidOperationException(SafeAxisMotionNotInjectedMessage);
|
||||
LogManager.LogSysError(exception);
|
||||
ShowOperationFailed(SafeAxisMotionNotInjectedMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
SafeAxisMotion.SafeMove(
|
||||
MotionMoveRequest.ForAxis(axisX, newRulerPoint.X),
|
||||
MotionMoveRequest.ForAxis(axisY, newRulerPoint.Y));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.LogSysError(ex);
|
||||
ShowOperationFailed(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ValidateMoveRange(double dx, double dy)
|
||||
{
|
||||
if (Math.Abs(dx) > DefaultFovX || Math.Abs(dy) > DefaultFovY)
|
||||
{
|
||||
LocalizedMessageBox.Show(MessageKey.ParamOutOfRange, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool ConfirmMove(Point newRulerPoint)
|
||||
{
|
||||
string message = string.Format("新点的坐标({0},{1}),是否移动?", newRulerPoint.X, newRulerPoint.Y);
|
||||
return MwMessageBox.Show(message, LanguageResourceHelper.GetString(MessageKey.TitleConfirm), MessageBoxButton.OKCancel, MessageBoxImage.Question, MessageBoxResult.Cancel) == MessageBoxResult.OK;
|
||||
}
|
||||
|
||||
private static void ShowDeviceNotInitialized()
|
||||
{
|
||||
LocalizedMessageBox.Show(MessageKey.DeviceNotInitialized, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
|
||||
private static void ShowOperationFailed(string message)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
LocalizedMessageBox.Show(MessageKey.CommonOperationFailed, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
MwMessageBox.Show(message, LanguageResourceHelper.GetString(MessageKey.TitleError), MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
using MainShell.EventArgsFolder;
|
||||
using MainShell.Log;
|
||||
using MainShell.Vision;
|
||||
using MwFramework.Device.Model;
|
||||
using MwFramework.Controls.ControlCanvas.DrawingControl;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using AppCameraType = MainShell.Common.CameraType;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace MainShell.Common.Display.ViewModel
|
||||
{
|
||||
public class CameraViewModel : Screen, IHandle<DisplayImageEventArgs>, IHandle<DisplayFindTemplateResultEventArgs>
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
public AppCameraType CameraType { get; }
|
||||
|
||||
private WriteableBitmap currentImage;
|
||||
private WriteableBitmap _displayImage;
|
||||
public WriteableBitmap DisplayImage
|
||||
{
|
||||
get { return _displayImage; }
|
||||
set
|
||||
{
|
||||
SetAndNotify(ref _displayImage, value);
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<object> _shapes = new ObservableCollection<object>();
|
||||
public ObservableCollection<object> Shapes
|
||||
{
|
||||
get { return _shapes; }
|
||||
set
|
||||
{
|
||||
if (_shapes != value) { _shapes = value; OnPropertyChanged(nameof(Shapes)); }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据 CameraData 更新并返回 WriteableBitmap。
|
||||
/// 优化要点:
|
||||
/// - 重用已有 WriteableBitmap(当尺寸与像素格式相同时)以减少分配。
|
||||
/// - 校验参数与缓冲区长度。
|
||||
/// - 捕获并记录异常,失败时返回 null(不抛出)。
|
||||
/// </summary>
|
||||
public WriteableBitmap UpdateBitmap(CameraData cameraData)
|
||||
{
|
||||
if (cameraData == null)
|
||||
{
|
||||
"图片数据为空".LogSysError();
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int width = (int)cameraData.Width;
|
||||
int height = (int)cameraData.Height;
|
||||
int bitCnt = cameraData.Bit;
|
||||
byte[] buffer = cameraData.BufferData;
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
{
|
||||
$"CameraViewModel.UpdateBitmap: invalid size {width}x{height}".LogSysError();
|
||||
return null;
|
||||
}
|
||||
|
||||
// 选择像素格式
|
||||
System.Windows.Media.PixelFormat pixelFormat = bitCnt == 1
|
||||
? System.Windows.Media.PixelFormats.Gray8
|
||||
: (bitCnt == 3 ? System.Windows.Media.PixelFormats.Bgr24 : System.Windows.Media.PixelFormats.Bgra32);
|
||||
|
||||
// 计算每行字节数(stride)
|
||||
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
|
||||
int stride = width * bytesPerPixel;
|
||||
long requiredLength = (long)stride * height;
|
||||
|
||||
if (buffer == null)
|
||||
{
|
||||
"CameraViewModel.UpdateBitmap: buffer is null".LogSysError();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (buffer.Length < requiredLength)
|
||||
{
|
||||
($"CameraViewModel.UpdateBitmap: buffer length {buffer.Length} is less than required {requiredLength}").LogSysError();
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果现有 bitmap 可复用(尺寸和格式一致),就重用以减少 GC/分配
|
||||
if (currentImage == null ||
|
||||
currentImage.PixelWidth != width ||
|
||||
currentImage.PixelHeight != height ||
|
||||
!currentImage.Format.Equals(pixelFormat))
|
||||
{
|
||||
// 新建 WriteableBitmap
|
||||
currentImage = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
|
||||
}
|
||||
|
||||
// 将字节拷贝到 BackBuffer(UI 线程中调用)
|
||||
currentImage.Lock();
|
||||
try
|
||||
{
|
||||
// BackBuffer 为 IntPtr,使用 Marshal.Copy 从 byte[] 拷贝
|
||||
System.Runtime.InteropServices.Marshal.Copy(buffer, 0, currentImage.BackBuffer, (int)requiredLength);
|
||||
currentImage.AddDirtyRect(new Int32Rect(0, 0, width, height));
|
||||
}
|
||||
finally
|
||||
{
|
||||
currentImage.Unlock();
|
||||
}
|
||||
|
||||
return currentImage;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
($"CameraViewModel.UpdateBitmap exception: {ex}").LogSysError();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public CameraViewModel(IEventAggregator eventAggregator, AppCameraType cameraType)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
CameraType = cameraType;
|
||||
_eventAggregator?.Subscribe(this);
|
||||
}
|
||||
|
||||
public void Handle(DisplayImageEventArgs message)
|
||||
{
|
||||
if (message == null || message.CameraType != CameraType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CommonUti.RunOnUi(() =>
|
||||
{
|
||||
WriteableBitmap bmp = UpdateBitmap(message.CameraData);
|
||||
// 只有在成功生成 bitmap 时才更新 DisplayImage,避免把 null 赋值导致 UI 清空
|
||||
if (bmp != null)
|
||||
{
|
||||
DisplayImage = bmp;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Handle(DisplayFindTemplateResultEventArgs message)
|
||||
{
|
||||
if (message == null || message.CameraType != CameraType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CommonUti.RunOnUi(() =>
|
||||
{
|
||||
ApplyTemplateResultShapes(message);
|
||||
});
|
||||
}
|
||||
|
||||
private void ApplyTemplateResultShapes(DisplayFindTemplateResultEventArgs message)
|
||||
{
|
||||
if (message.ClearShapesBeforeDisplay)
|
||||
{
|
||||
Shapes.Clear();
|
||||
}
|
||||
|
||||
if (message.Result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AppendCenterShapes(message.Result);
|
||||
AppendContourShape(message.Result.Contour);
|
||||
AppendCircleShapes(message.Result.Circles);
|
||||
AppendLineShapes(message.Result.Lines);
|
||||
AppendRectangleShapes(message.Result.Rectangles);
|
||||
}
|
||||
|
||||
private void AppendCenterShapes(FindTemplateResult result)
|
||||
{
|
||||
if (result == null || !AreFinite(result.CenterX, result.CenterY, result.Score))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShapeDrawing pointShape = new ShapeDrawing();
|
||||
pointShape.X = result.CenterX;
|
||||
pointShape.Y = result.CenterY;
|
||||
Shapes.Add(pointShape);
|
||||
|
||||
TextShapeDrawing textShape = new TextShapeDrawing();
|
||||
textShape.X = result.CenterX;
|
||||
textShape.Y = result.CenterY;
|
||||
textShape.Text = $"Score:{result.Score:F3}";
|
||||
Shapes.Add(textShape);
|
||||
}
|
||||
|
||||
private void AppendContourShape(FindTemplateContourResult contour)
|
||||
{
|
||||
if (contour == null || !AreFinite(contour.StartX, contour.StartY, contour.EndX, contour.EndY))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RectShapeDrawing contourShape = new RectShapeDrawing();
|
||||
contourShape.X = contour.StartX;
|
||||
contourShape.Y = contour.StartY;
|
||||
contourShape.X1 = contour.EndX;
|
||||
contourShape.Y1 = contour.EndY;
|
||||
Shapes.Add(contourShape);
|
||||
}
|
||||
|
||||
private void AppendCircleShapes(IList<FindTemplateCircleResult> circles)
|
||||
{
|
||||
if (circles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (FindTemplateCircleResult circle in circles)
|
||||
{
|
||||
if (circle == null || !AreFinite(circle.CenterX, circle.CenterY, circle.Radius))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CircleShapeDrawing circleShape = new CircleShapeDrawing();
|
||||
circleShape.X = circle.CenterX;
|
||||
circleShape.Y = circle.CenterY;
|
||||
circleShape.CenterPoint = new Point(circle.CenterX, circle.CenterY);
|
||||
circleShape.RadiusX = circle.Radius;
|
||||
circleShape.RadiusY = circle.Radius;
|
||||
circleShape.LineWidth = 1;
|
||||
circleShape.FillColor = Brushes.Blue;
|
||||
Shapes.Add(circleShape);
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendLineShapes(IList<FindTemplateLineResult> lines)
|
||||
{
|
||||
if (lines == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (FindTemplateLineResult line in lines)
|
||||
{
|
||||
if (line == null || !AreFinite(line.StartX, line.StartY, line.EndX, line.EndY))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LineShapeDrawing lineShape = new LineShapeDrawing();
|
||||
lineShape.X = line.StartX;
|
||||
lineShape.Y = line.StartY;
|
||||
lineShape.X1 = line.EndX;
|
||||
lineShape.Y1 = line.EndY;
|
||||
Shapes.Add(lineShape);
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendRectangleShapes(IList<FindTemplateRectangleResult> rectangles)
|
||||
{
|
||||
if (rectangles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (FindTemplateRectangleResult rectangle in rectangles)
|
||||
{
|
||||
if (rectangle == null || !AreFinite(rectangle.StartX, rectangle.StartY, rectangle.Width, rectangle.Height, rectangle.Angle))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
double halfWidth = rectangle.Width / 2d;
|
||||
double halfHeight = rectangle.Height / 2d;
|
||||
double cosAngle = Math.Cos(rectangle.Angle);
|
||||
double sinAngle = Math.Sin(rectangle.Angle);
|
||||
double centerX = rectangle.StartX + (halfWidth * cosAngle) - (halfHeight * sinAngle);
|
||||
double centerY = rectangle.StartY + (halfWidth * sinAngle) + (halfHeight * cosAngle);
|
||||
|
||||
RectShape2Drawing rectangleShape = new RectShape2Drawing();
|
||||
rectangleShape.X = centerX;
|
||||
rectangleShape.Y = centerY;
|
||||
rectangleShape.CenterX = centerX;
|
||||
rectangleShape.CenterY = centerY;
|
||||
rectangleShape.HalfWidth = halfWidth;
|
||||
rectangleShape.HalfHeigth = halfHeight;
|
||||
rectangleShape.Angle = rectangle.Angle;
|
||||
Shapes.Add(rectangleShape);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AreFinite(params double[] values)
|
||||
{
|
||||
if (values == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (double value in values)
|
||||
{
|
||||
if (double.IsNaN(value) || double.IsInfinity(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user