2026-01-26 18:56:53 +09:00

329 lines
15 KiB
C#

using CoreUnit.Control.UserControl.Canvas;
using CoreUnit.Scanner.UserControl.ScannerCanvas;
using IxMilia.Dxf.Entities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Security.Cryptography;
namespace GUI.Common
{
static class ParserHelper
{
static public AddObjectParam GetCandidate(
this AddObjectParam insert,
AddObjectParam nonInsert,
RectangleF rect)
{
var startPoint = new UnitPoint(
insert.Point1.X + rect.X,
insert.Point1.Y + rect.Y);
switch (nonInsert.ObjectType) {
case "ArcCR":
return new AddObjectParam {
ObjectType = "ArcCR",
Center = new UnitPoint(startPoint.X + nonInsert.MajorRadius, startPoint.Y + nonInsert.MajorRadius),
StartAngle = (float)0,
EndAngle = (float)360,
MajorRadius = (float)nonInsert.MajorRadius
};
case "Line":
return new AddObjectParam {
ObjectType = "Line",
Point1 = nonInsert.Point1 + startPoint,
Point2 = nonInsert.Point2 + startPoint,
};
case "Dot":
return new AddObjectParam {
ObjectType = "Dot",
Point1 = startPoint + nonInsert.Point1,
};
case "PolyLine":
return new AddObjectParam {
ObjectType = "Polyline",
Point1 = nonInsert.Point1 + startPoint,
Point2 = nonInsert.Point2 + startPoint,
};
case "Ellipse":
return new AddObjectParam {
ObjectType = "Ellipse",
Center = new UnitPoint(startPoint.X + nonInsert.MajorRadius, startPoint.Y + nonInsert.MajorRadius),
Point1 = startPoint + nonInsert.Point1,
Point2 = startPoint + nonInsert.Point1,
RotateAngle = nonInsert.RotateAngle
};
case "ZigZag":
return new AddObjectParam {
ObjectType = "ZigZag",
Point1 = nonInsert.Point1 + startPoint,
Point2 = nonInsert.Point2 + startPoint,
Pitch = nonInsert.Pitch,
Amplitude = nonInsert.Amplitude,
Radius = nonInsert.Radius,
RotateAngle = nonInsert.RotateAngle,
DrawDirection = nonInsert.DrawDirection
};
default:
Console.WriteLine($"Entity type: {nonInsert.ObjectType}");
return new AddObjectParam();
}
}
static public List<IDrawObject> AddObjects(
this IEnumerable<AddObjectParam> dataModelParams,
ScannerCanvasUserCtrl scannerCanvas)
{
var drawObjects = new List<IDrawObject>();
dataModelParams.ToList().ForEach(param =>
drawObjects.Add(scannerCanvas.AddObject(param)));
scannerCanvas.FinalizeGrouping();
return drawObjects;
}
static List<int> FindArcCloseToNextLine(IList<DxfEntity> entities, double pointTolerance)
{
// Arc의 시작점과 그 다음 Line의 시작점이 tolerance 이하일 경우 해당 Arc를 List에 저장
var arcIndices = new List<int>();
for (int i = 0; i < entities.Count - 1; i++) {
if (entities[i].EntityType == DxfEntityType.Arc &&
entities[i + 1].EntityType == DxfEntityType.Line) {
var arc = (DxfArc)entities[i];
var line = (DxfLine)entities[i + 1];
// Arc 시작점 계산
var arcStartX = arc.Center.X + arc.Radius * Math.Cos(DegreesToRadians(arc.StartAngle));
var arcStartY = arc.Center.Y + arc.Radius * Math.Sin(DegreesToRadians(arc.StartAngle));
// Line 시작점
var lineStartX = line.P1.X;
var lineStartY = line.P1.Y;
// 거리 계산
double dx = arcStartX - lineStartX;
double dy = arcStartY - lineStartY;
double dist = Math.Sqrt(dx * dx + dy * dy);
if (dist <= pointTolerance) {
arcIndices.Add(i); // 해당 Arc 인덱스 저장
}
}
}
return arcIndices;
}
static double DegreesToRadians(double degrees)
{
return degrees * Math.PI / 180.0;
}
static public IEnumerable<AddObjectParam> GetEntity(
this IList<DxfEntity> dxfEntities)
{
var dataModelParams = new List<AddObjectParam>();
// 1. Arc-다음 Line 시작점이 가까운 Arc 인덱스 찾기
var arcIndicesToCW = FindArcCloseToNextLine(dxfEntities, pointTolerance: 0.1);
// 2. 엔티티 처리
for (int i = 0; i < dxfEntities.Count; i++) {
var entity = dxfEntities[i];
bool isArcToCW = arcIndicesToCW.Contains(i);
switch (entity.EntityType) {
case DxfEntityType.Line:
var line = (DxfLine)entity;
Console.WriteLine($"Line from {line.P1} to {line.P2}");
dataModelParams.Add(new AddObjectParam {
ObjectType = "Line",
Point1 = new UnitPoint(line.P1.X, line.P1.Y),
Point2 = new UnitPoint(line.P2.X, line.P2.Y)
});
break;
case DxfEntityType.Circle:
var circle = (DxfCircle)entity;
Console.WriteLine($"Circle with center {circle.Center} and radius {circle.Radius}");
dataModelParams.Add(new AddObjectParam {
ObjectType = "ArcCR",
Center = new UnitPoint(circle.Center.X, circle.Center.Y),
StartAngle = 0f,
EndAngle = 360f,
MajorRadius = (float)circle.Radius
});
break;
case DxfEntityType.Arc:
var arc = (DxfArc)entity;
float startAngle = (float)Math.Round((float)arc.StartAngle, 0);
float endAngle = (float)Math.Round((float)arc.EndAngle, 0);
string direction = "CCW";
if (isArcToCW) {
direction = "CW";
// CW이면 Start/End 스왑
float temp = startAngle;
startAngle = endAngle;
endAngle = temp;
}
float sweepAngle = endAngle - startAngle;
if (direction == "CCW" && sweepAngle < 0) sweepAngle += 360;
if (direction == "CW" && sweepAngle > 0) sweepAngle -= 360;
Console.WriteLine($"Arc with center {arc.Center}, radius {arc.Radius}, start angle {startAngle}, end angle {endAngle}, direction {direction}");
dataModelParams.Add(new AddObjectParam {
ObjectType = "ArcCR",
Center = new UnitPoint(arc.Center.X, arc.Center.Y),
StartAngle = startAngle,
EndAngle = endAngle,
SweepAngle = sweepAngle,
MajorRadius = (float)arc.Radius,
Direction = direction
});
break;
case DxfEntityType.LwPolyline:
var polyline = (DxfLwPolyline)entity;
Console.WriteLine($"LwPolyline with {polyline.Vertices.Count} vertices:");
for (int v = 0; v < polyline.Vertices.Count; v++) {
var vertex = polyline.Vertices[v];
var nextVertex = v < polyline.Vertices.Count - 1 ? polyline.Vertices[v + 1] : polyline.Vertices[0];
dataModelParams.Add(new AddObjectParam {
ObjectType = "PolyLine",
Point1 = new UnitPoint(vertex.X, vertex.Y),
Point2 = new UnitPoint(nextVertex.X, nextVertex.Y)
});
}
break;
case DxfEntityType.Insert:
var insert = (DxfInsert)entity;
Console.WriteLine($"Insert block at position ({insert.Location.X}, {insert.Location.Y}, {insert.Location.Z})");
dataModelParams.Add(new AddObjectParam {
ObjectType = "Insert",
Point1 = new UnitPoint(insert.Location.X, insert.Location.Y)
});
break;
case DxfEntityType.Ellipse:
var ellipse = (DxfEllipse)entity;
Console.WriteLine($"Ellipse with center {ellipse.Center}, major axis direction {ellipse.MajorAxis}, and normal {ellipse.Normal}, start {ellipse.StartParameter}, end {ellipse.EndParameter}");
var point1 = new UnitPoint(
ellipse.Center.X - ellipse.MajorAxis.Length,
ellipse.Center.Y - ellipse.MinorAxis().Length);
var point2 = new UnitPoint(
ellipse.Center.X + ellipse.MajorAxis.Length,
ellipse.Center.Y + ellipse.MinorAxis().Length);
dataModelParams.Add(new AddObjectParam {
ObjectType = "Ellipse",
Center = new UnitPoint(ellipse.Center.X, ellipse.Center.Y),
Point1 = point1,
Point2 = point2,
StartAngle = (float)HitUtil.RadiansToDegrees(ellipse.StartParameter),
EndAngle = (float)HitUtil.RadiansToDegrees(ellipse.EndParameter),
RotateAngle = CalculateRotationAngle(ellipse)
});
break;
case DxfEntityType.Point:
var modelPoint = (DxfModelPoint)entity;
Console.WriteLine($"ModelPoint at ({modelPoint.Location.X}, {modelPoint.Location.Y}, {modelPoint.Location.Z})");
dataModelParams.Add(new AddObjectParam {
ObjectType = "Dot",
Point1 = new UnitPoint(modelPoint.Location.X, modelPoint.Location.Y),
});
break;
// 다른 도형 타입에 대한 처리 추가 가능
default:
Console.WriteLine($"Entity type: {entity.EntityType}");
break;
}
}
return dataModelParams;
}
static public RectangleF GetRect(
this IList<IDrawObject> drawObjects)
{
List<UnitPoint> ptList = new List<UnitPoint>();
drawObjects.ToList().ForEach(obj => {
switch (obj) {
case Line _:
ptList.Add(((Line)obj).P1);
ptList.Add(((Line)obj).P2);
break;
case Dot _:
ptList.Add(((Dot)obj).P1);
break;
case Spline _:
ptList.Add(((Spline)obj).Center);
break;
case SnowMan _:
ptList.Add(((SnowMan)obj).P1);
ptList.Add(((SnowMan)obj).P2);
break;
case Group _:
ptList.Add(((Group)obj).P1);
ptList.Add(((Group)obj).P2);
ptList.Add(((Group)obj).P3);
ptList.Add(((Group)obj).P4);
break;
case Arc3Point _: {
RectangleF tempRect = ((Arc3Point)obj).ClientRect;
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top));
break;
}
case Arc _: {
RectangleF tempRect = ((Arc)obj).ClientRect;
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top));
break;
}
case ZigZag _:
ptList.Add(((ZigZag)obj).P1);
ptList.Add(((ZigZag)obj).P2);
break;
case EllipseTool _: {
RectangleF tempRect = ((EllipseTool)obj).ClientRect;
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top));
break;
}
case RectangleTool _: {
RectangleF tempRect = ((RectangleTool)obj).ClientRect;
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom));
ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top));
break;
}
}
});
return ScreenUtils.GetRect(ptList, 0);
}
static public float CalculateRotationAngle(
DxfEllipse ellipse)
{
// MajorAxis와 MinorAxis를 사용하여 회전 각도를 계산
var majorAxis = ellipse.MajorAxis;
float angle = (float)(Math.Atan2(majorAxis.Y, majorAxis.X) * (180.0 / Math.PI));
return angle;
}
}
}