2026-06-05 13:44:39 +09:00

213 lines
7.1 KiB
C#

/*
* Copyright (c) 2022 LG Electronics Inc.
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
*/
using Aurora.View;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace AuroraUIComponent.UserControls
{
public class LWPolyLinePattern : IPattern
{
// DXF 의 LWPolyLine 의 데이터를 기준으로 일단 정의
// 자료를 보면, x, y, start width, end width, bulge value 로 구성되는데,
// 일단은 x, y, bulge 로만 구성 (추후 필요시 수정)
public class PathElement : NotifyPropertyChangedBase
{
public double X { get => _X; set => SetProperty(ref _X, value); }
private double _X;
public double Y { get => _Y; set => SetProperty(ref _Y, value); }
private double _Y;
public double Bulge { get => _Bulge; set => SetProperty(ref _Bulge, value); }
private double _Bulge;
public Brush CustomBrush = null;
public PathElement() : this(0, 0, 0)
{
}
public PathElement(PathElement org, string brush = null)
{
X = org.X;
Y = org.Y;
Bulge = org.Bulge;
if (brush != null) {
CustomBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(brush));
}
}
public PathElement(double x, double y, double r = 0, string brush = null)
{
X = x;
Y = y;
Bulge = r;
if (brush != null) {
CustomBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(brush));
}
}
}
public ObservableCollection<PathElement> Entities { get => _ListPath; set => SetProperty(ref _ListPath, value); }
private ObservableCollection<PathElement> _ListPath;
private double minX;
private double maxX;
private double minY;
private double maxY;
public LWPolyLinePattern()
{
Entities = new ObservableCollection<PathElement>();
}
public void Copy(LWPolyLinePattern copyPattern)
{
if (copyPattern != null) {
//Entities.Clear();
//foreach (var item in copyPattern.Entities) {
// Entities.Add(item);
//}
// ObservableCollection Clear/Add/Remove 시 매번 UI Update 발생하여 Delay -> 최대한 Element 개수는 변하지 않도록 아래와 같이 수정.
// 코드 유지보수에는 위처럼 Clear/Add하는 게 심플하지만, Performance를 위해 우선 아래와 같이 적용해 봄
int i = 0;
for (; i < Entities.Count && i < copyPattern.Entities.Count; i++) {
Entities[i].X = copyPattern.Entities[i].X;
Entities[i].Y = copyPattern.Entities[i].Y;
Entities[i].Bulge = copyPattern.Entities[i].Bulge;
}
if (Entities.Count < copyPattern.Entities.Count) {
for (; i < copyPattern.Entities.Count; i++) {
Entities.Add(new PathElement(copyPattern.Entities[i]));
}
}
if (Entities.Count > copyPattern.Entities.Count) {
while (copyPattern.Entities.Count < Entities.Count) {
Entities.RemoveAt(i);
}
}
NotifyPropertyChanged("Entities");
UpdateCalculatedPath();
}
}
public void Clear()
{
Entities.Clear();
//Entities.Add(new Rect());
}
public void UpdateCalculatedPath()
{
UpdateCalculatedPath(0, 0, 1.0);
}
public void UpdateCalculatedPath(double offsetX, double offsetY, double ratio)
{
for (int i = 0; i < Entities.Count; i++) {
Entities[i].X = (Entities[i].X + offsetX) * ratio;
Entities[i].Y = (Entities[i].Y + offsetY) * ratio;
Entities[i].Bulge = Entities[i].Bulge;
}
NotifyPropertyChanged("Entities");
UpdateMinMaxXY();
}
private void UpdateMinMaxXY()
{
if (Entities != null && Entities.Count > 0) {
minX = Entities[0].X;
maxX = Entities[0].X;
minY = Entities[0].Y;
maxY = Entities[0].Y;
foreach (var item in Entities) {
if (item.X < minX) minX = item.X;
if (item.X > maxX) maxX = item.X;
if (item.Y < minY) minY = item.Y;
if (item.Y > maxY) maxY = item.Y;
}
}
}
public void FitToTPArea(double tpWidth, double tpHeight)
{
if (Entities.Count > 0) {
UpdateMinMaxXY();
double ratio = tpWidth / (maxX - minX) < tpHeight / (maxY - minY) ?
tpWidth / (maxX - minX) : tpHeight / (maxY - minY);
UpdateCalculatedPath((tpWidth / ratio - minX - maxX) / 2, (tpHeight / ratio - minY - maxY) / 2, ratio);
}
}
public void FitCenterToTPArea(double tpWidth, double tpHeight)
{
if (Entities.Count > 0) {
double minX = Entities[0].X;
double maxX = Entities[0].X;
double minY = Entities[0].Y;
double maxY = Entities[0].Y;
foreach (var item in Entities) {
if (item.X < minX) minX = item.X;
if (item.X > maxX) maxX = item.X;
if (item.Y < minY) minY = item.Y;
if (item.Y > maxY) maxY = item.Y;
}
UpdateCalculatedPath((tpWidth - minX - maxX) / 2, (tpHeight - minY - maxY) / 2, 1.0);
}
}
public void ShiftX(double delta)
{
UpdateCalculatedPath(delta, 0, 1.0);
}
public void ShiftY(double delta)
{
UpdateCalculatedPath(0, delta, 1.0);
}
public override void Shift(double x, double y)
{
UpdateCalculatedPath(x, y, 1.0);
}
public override bool GetMinMax(out double minX, out double maxX, out double minY, out double maxY)
{
if (Entities.Count == 0) {
return base.GetMinMax(out minX, out maxX, out minY, out maxY);
}
minX = maxX = Entities[0].X;
minY = maxY = Entities[0].Y;
foreach (var item in Entities) {
if (minX > item.X) minX = item.X;
if (minY > item.Y) minY = item.Y;
if (maxX < item.X) maxX = item.X;
if (maxY < item.Y) maxY = item.Y;
// TODO: Arc로 벗어나는 부분까지 계산
}
return true;
}
}
}