213 lines
7.1 KiB
C#
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;
|
|
}
|
|
}
|
|
} |