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

687 lines
21 KiB
C#

using CoreUnit.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text.Json;
using System.Windows.Forms;
using System.Xml;
namespace CoreUnit.Control.UserControl.Canvas
{
public class RoiTool : DrawObjectBase, ISerialize, IDrawObject
{
protected UnitPoint m_startPoint = UnitPoint.Empty;
protected UnitPoint m_endPoint = UnitPoint.Empty;
UnitPoint m_P1; //사각형에서 Left,Top
[Browsable(false)]
public UnitPoint P1 {
get { return m_P1; }
set { m_P1 = value; }
}
UnitPoint m_P2; //사각형에서 Left,Bottom
[Browsable(false)]
public UnitPoint P2 {
get { return m_P2; }
set { m_P2 = value; }
}
UnitPoint m_P3; //사각형에서 Right,Bottom
[Browsable(false)]
public UnitPoint P3 {
get { return m_P3; }
set { m_P3 = value; }
}
UnitPoint m_P4;//사각형에서 Right,Top
[Browsable(false)]
public UnitPoint P4 {
get { return m_P4; }
set { m_P4 = value; }
}
[Browsable(false)]
public UnitPoint P12 {
get {
UnitPoint newPoint = new UnitPoint(P1.X / 2 + P2.X / 2, P1.Y / 2 + P2.Y / 2);
return newPoint;
}
}
[Browsable(false)]
public UnitPoint P23 {
get {
UnitPoint newPoint = new UnitPoint(P2.X / 2 + P3.X / 2, P2.Y / 2 + P3.Y / 2);
return newPoint;
}
}
[Browsable(false)]
public UnitPoint P34 {
get {
UnitPoint newPoint = new UnitPoint(P3.X / 2 + P4.X / 2, P3.Y / 2 + P4.Y / 2);
return newPoint;
}
}
[Browsable(false)]
public UnitPoint P41 {
get {
UnitPoint newPoint = new UnitPoint(P4.X / 2 + P1.X / 2, P4.Y / 2 + P1.Y / 2);
return newPoint;
}
}
[Browsable(true)]
[ReadOnly(true)]
[Category("1.Boundary")]
[DisplayName("Left,Bottom,Right,Top")]
[Description("Boundary of Object")]
public RectangleF ClientRect {
get {
List<UnitPoint> points = new List<UnitPoint> { P1, P2, P3, P4 };
return ScreenUtils.GetRect(points, 0);
}
}
[Browsable(false)]
public UnitPoint Center {
get { return new UnitPoint(MiddlePoint.X, MiddlePoint.Y); }
set { MiddlePoint = value.Point; }
}
[Browsable(true)]
[ReadOnly(false)]
[Category("2. Geometry")]
[DisplayName("Center")]
[Description("Center Of ROI")]
[XmlSerializable]
[TypeConverter(typeof(PointFConverter))]
public PointF MiddlePoint {
get {
return HitUtil.LineMidpoint(P2, P4).Point;
}
set {
PointF offset = new PointF();
offset.X = (value.X - MiddlePoint.X);
offset.Y = (value.Y - MiddlePoint.Y);
Move(new UnitPoint(offset));
}
}
[Browsable(true)]
[ReadOnly(false)]
[Category("2. Geometry")]
[DisplayName("Width")]
[Description("Width Of ROI")]
[XmlSerializable]
public double RoiWidth {
get { return Math.Round(HitUtil.Distance(P1, P4), 3); }
set {
double distance = value;
MakeWidth(MiddlePoint, distance);
}
}
[Browsable(true)]
[ReadOnly(false)]
[Category("2. Geometry")]
[DisplayName("Height")]
[Description("Height Of ROI")]
[XmlSerializable]
public double RoiHeight {
get { return Math.Round(HitUtil.Distance(P1, P2), 3); }
set {
double distance = value;
MakeHeight(MiddlePoint, distance);
}
}
string m_visionProcessType;
[Browsable(true)]
[ReadOnly(true)]
[Category("3. Paramter")]
[DisplayName("Vision Process Type")]
[Description("Vision Process Type")]
[XmlSerializable]
public string VisionProcessType {
get { return m_visionProcessType; }
set {
m_visionProcessType = value;
}
}
int m_alignId = -1;
[Browsable(true)]
[ReadOnly(false)]
[Category("3. Parameter")]
[DisplayName("Align ID")]
[Description("Align ID")]
[XmlSerializable]
public int AlignID {
get { return m_alignId; }
set { m_alignId = value; }
}
string m_type;
[Browsable(false)]
public virtual string Type {
get {
m_type = RoiTool.ObjectType;
return m_type;
}
set { m_type = value; }
}
public static string ObjectType {
get { return "Roi"; }
}
public RoiTool()
{
}
public RoiTool(string visionProcessType)
{
VisionProcessType = visionProcessType;
}
static int ThresholdPixel = 6;
static float ThresholdWidth(ICanvas canvas, float objectwidth)
{
return ThresholdWidth(canvas, objectwidth, ThresholdPixel);
}
public static float ThresholdWidth(ICanvas canvas, float objectwidth, float pixelwidth)
{
double minWidth = canvas.ToUnit(pixelwidth);
double width = Math.Max(objectwidth / 2, minWidth);
return (float)width;
}
public override void InitializeFromModel(UnitPoint point, DrawingLayer layer, ISnapPoint snap)
{
m_startPoint = m_endPoint = P1 = P2 = P3 = P4 = point;
Width = layer.Width;
Color = layer.Color;
Selected = true;
}
public void Copy(RoiTool acopy)
{
base.Copy(acopy);
m_startPoint = acopy.P1;
m_endPoint = acopy.P3;
P1 = acopy.P1;
P2 = acopy.P2;
P3 = acopy.P3;
P4 = acopy.P4;
Selected = acopy.Selected;
VisionProcessType = acopy.VisionProcessType;
}
public void SaveRoiImage(string fileName, Bitmap image)
{
}
#region IDrawObject Members
public virtual IDrawObject Clone()
{
RoiTool a = new RoiTool();
a.Copy(this);
return a;
}
public RectangleF GetBoundingRect(ICanvas canvas)
{
float thWidth = ThresholdWidth(canvas, Width, ThresholdPixel);
if (thWidth < Width) {
thWidth = Width;
}
List<UnitPoint> points = new List<UnitPoint> { P1, P2, P3, P4 };
return ScreenUtils.GetRect(points, thWidth);
}
public void Draw(ICanvas canvas, RectangleF unitrect)
{
Color color = Color.Red;
Pen pen = canvas.CreatePen(color, Width);
//2. Group객체의 가장자리 bound draw 함수
if (Highlighted || Selected) {
//3.Rectangle 객체에 대한 중심 위치 점 draw 함수
//pen = DrawUtils.SelectedPen;
if (Locked == false) {
canvas.DrawArc(canvas, pen, new UnitPoint(Center.X, Center.Y), 1, 0, 360);
DrawUtils.DrawNode(canvas, P1);
DrawUtils.DrawNode(canvas, P2);
DrawUtils.DrawNode(canvas, P3);
DrawUtils.DrawNode(canvas, P4);
DrawUtils.DrawNode(canvas, P12);
DrawUtils.DrawNode(canvas, P23);
DrawUtils.DrawNode(canvas, P34);
DrawUtils.DrawNode(canvas, P41);
}
}
canvas.DrawLines(canvas, pen, new List<UnitPoint>() { P1, P2, P3, P4 });
}
public bool PointInObject(ICanvas canvas, UnitPoint point)
{
RectangleF boundingrect = GetBoundingRect(canvas);
return boundingrect.Contains(point.Point);
}
public bool ObjectInRectangle(ICanvas canvas, RectangleF rect, bool anyPoint)
{
RectangleF boundingrect = GetBoundingRect(canvas);
if (anyPoint) {
return (HitUtil.LineIntersectWithRect(P1, P2, rect) || HitUtil.LineIntersectWithRect(P3, P4, rect));
}
return rect.Contains(boundingrect);
}
public void OnMouseMove(ICanvas canvas, UnitPoint point)
{
if (Locked == false) {
m_endPoint = point;
DrawBound(m_startPoint, m_endPoint);
}
}
public void DrawBound(UnitPoint startPoint, UnitPoint endPoint)
{
P1 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y));
P2 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y));
P3 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y));
P4 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y));
}
public eDrawObjectMouseDown OnMouseDown(ICanvas canvas, UnitPoint point, ISnapPoint snappoint)
{
Selected = false;
return eDrawObjectMouseDown.Done;
}
public void OnMouseUp(ICanvas canvas, UnitPoint point, ISnapPoint snappoint)
{
}
public void OnKeyDown(ICanvas canvas, KeyEventArgs e)
{
}
[Browsable(false)]
public UnitPoint RepeatStartingPoint {
get { return UnitPoint.Empty; }
}
public INodePoint NodePoint(ICanvas canvas, UnitPoint point)
{
if (Locked == false) {
float thWidth = ThresholdWidth(canvas, Width);
#region Node Point Edge
if (HitUtil.CircleHitPoint(P1, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P1);
}
if (HitUtil.CircleHitPoint(P2, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P2);
}
if (HitUtil.CircleHitPoint(P3, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P3);
}
if (HitUtil.CircleHitPoint(P4, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P4);
}
if (HitUtil.CircleHitPoint(P12, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P12);
}
if (HitUtil.CircleHitPoint(P23, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P23);
}
if (HitUtil.CircleHitPoint(P34, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P34);
}
if (HitUtil.CircleHitPoint(P41, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.P41);
}
if (HitUtil.CircleHitPoint(Center, thWidth, point)) {
return new NodePointRoiEdge(this, NodePointRoiEdge.ePoint.Center);
}
}
#endregion
return null;
}
public ISnapPoint SnapPoint(ICanvas canvas, UnitPoint point, List<IDrawObject> otherobj, Type[] runningsnaptypes, Type usersnaptype)
{
return null;
}
public void Move(UnitPoint offset)
{
m_P1.X += offset.X;
m_P1.Y += offset.Y;
m_P2.X += offset.X;
m_P2.Y += offset.Y;
m_P3.X += offset.X;
m_P3.Y += offset.Y;
m_P4.X += offset.X;
m_P4.Y += offset.Y;
}
public void Rotate(float angle, UnitPoint center)
{
P1 = HitUtil.RotatePoint(angle, P1, center);
P2 = HitUtil.RotatePoint(angle, P2, center);
P3 = HitUtil.RotatePoint(angle, P3, center);
P4 = HitUtil.RotatePoint(angle, P4, center);
}
public void MakeLength(float distance)
{
}
public void MakeWidth(PointF center, double width)
{
P1 = new UnitPoint(center.X - width / 2, P1.Y);
P2 = new UnitPoint(center.X - width / 2, P2.Y);
P3 = new UnitPoint(center.X + width / 2, P3.Y);
P4 = new UnitPoint(center.X + width / 2, P4.Y);
}
public void MakeHeight(PointF center, double height)
{
P1 = new UnitPoint(P1.X, center.Y + height / 2);
P2 = new UnitPoint(P2.X, center.Y - height / 2);
P3 = new UnitPoint(P3.X, center.Y - height / 2);
P4 = new UnitPoint(P4.X, center.Y + height / 2);
}
public virtual string GetInfoAsString()
{
return string.Format("{1:D3} {0}@Boundary:{2:F3}",
this.Type,
No + 1,
ClientRect);
}
#endregion
#region 1.마킹객체에 대한 속성
bool m_enabled = true;
[Browsable(false)]
public bool Enabled {
get { return m_enabled; }
set { m_enabled = value; }
}
uint m_markingCount = 1;
[Browsable(false)]
public uint MarkingCount {
get { return m_markingCount; }
set { m_markingCount = value; }
}
[Browsable(false)]
public PointF PF1 {
get { return P1.Point; }
set { P1 = new UnitPoint(value); }
}
[Browsable(false)]
public PointF PF2 {
get { return P2.Point; }
set { P2 = new UnitPoint(value); }
}
[Browsable(false)]
public PointF PF3 {
get { return P3.Point; }
set { P3 = new UnitPoint(value); }
}
[Browsable(false)]
public PointF PF4 {
get { return P4.Point; }
set { P4 = new UnitPoint(value); }
}
[Browsable(false)]
public float Angle {
get { return (float)Math.Round(HitUtil.RadiansToDegrees(HitUtil.LineAngleR(P1, P4, 0)), 3); ; }
set {
float angle = value - Angle;
Rotate(angle, Center);
}
}
int m_no;
[Browsable(false)]
public int No {
get { return m_no; }
set { m_no = value; }
}
[Browsable(false)]
public int ScannerParamID {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
#endregion
#region ISerialize
public virtual void GetObjectData(XmlWriter wr)
{
wr.WriteStartElement(Type);
Common.XmlUtil.WriteProperties(this, wr);
wr.WriteEndElement();
}
public virtual string GetObjectData()
{
string jsonString = string.Empty;
var options = new JsonSerializerOptions { WriteIndented = true };
try {
jsonString += JsonSerializer.Serialize(this, options);
} catch {
}
return jsonString;
}
private void GetRectangleObjectData(IDrawObject obj, XmlWriter wr)
{
wr.WriteStartElement(obj.Type);
Common.XmlUtil.WriteProperties(obj, wr);
wr.WriteEndElement();
}
public void AfterSerializedIn()
{
}
#endregion
}
public class NodePointRoiEdge : INodePoint
{
public enum ePoint
{
P1,
P2,
P3,
P4,
P12,
P23,
P34,
P41,
Center
}
static bool m_angleLocked = false;
RoiTool m_owner;
RoiTool m_clone;
UnitPoint m_originalPoint;
public UnitPoint OriginalPoint {
get { lock (this) { return m_originalPoint; } }
set { lock (this) { m_originalPoint = value; } }
}
UnitPoint m_endPoint;
public UnitPoint EndPoint {
get { lock (this) { return m_endPoint; } }
set { lock (this) { m_endPoint = value; } }
}
ePoint m_pointId;
public ePoint PointId {
get { lock (this) { return m_pointId; } }
set { lock (this) { m_pointId = value; } }
}
public NodePointRoiEdge(RoiTool owner, ePoint id)
{
m_owner = owner;
m_clone = m_owner.Clone() as RoiTool;
m_pointId = id;
m_originalPoint = GetPoint(m_pointId);
}
#region INodePoint Members
public IDrawObject GetClone()
{
return m_clone;
}
public IDrawObject GetOriginal()
{
return m_owner;
}
public void SetPosition(UnitPoint pos) //변경되는 위치의 포인터 값
{
SetPoint(m_pointId, pos, m_clone);
}
public void Finish()
{
m_endPoint = GetPoint(m_pointId);
m_owner.P1 = m_clone.P1;
m_owner.P2 = m_clone.P2;
m_owner.P3 = m_clone.P3;
m_owner.P4 = m_clone.P4;
m_clone = null;
}
public void Cancel()
{
}
public void Undo()
{
SetPoint(m_pointId, m_originalPoint, m_owner);
}
public void Redo()
{
SetPoint(m_pointId, m_endPoint, m_owner);
}
public void OnKeyDown(ICanvas canvas, KeyEventArgs e)
{
if (e.KeyCode == Keys.L) {
m_angleLocked = !m_angleLocked;
e.Handled = true;
}
}
#endregion
protected UnitPoint GetPoint(ePoint pointid)
{
if (pointid == ePoint.P1)
return m_clone.P1;
if (pointid == ePoint.P2)
return m_clone.P2;
if (pointid == ePoint.P3)
return m_clone.P3;
if (pointid == ePoint.P4)
return m_clone.P4;
if (pointid == ePoint.P12)
return m_clone.P12;
if (pointid == ePoint.P23)
return m_clone.P23;
if (pointid == ePoint.P34)
return m_clone.P34;
if (pointid == ePoint.P41)
return m_clone.P41;
return m_owner.P1;
}
protected void SetPoint(ePoint pointid, UnitPoint point, RoiTool rect)
{
UnitPoint startPoint = new UnitPoint(0, 0);
UnitPoint endPoint = point;
if (pointid == ePoint.P1 || pointid == ePoint.P2 || pointid == ePoint.P3 || pointid == ePoint.P4) {
if (pointid == ePoint.P1) {
startPoint = rect.P3;
} else if (pointid == ePoint.P2) {
startPoint = rect.P4;
} else if (pointid == ePoint.P3) {
startPoint = rect.P1;
} else if (pointid == ePoint.P4) {
startPoint = rect.P2;
}
rect.P1 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y));
rect.P2 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y));
rect.P3 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y));
rect.P4 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y));
} else if (pointid == ePoint.P12 || pointid == ePoint.P23 || pointid == ePoint.P34 || pointid == ePoint.P41) {
if (pointid == ePoint.P12) {
startPoint = rect.P34;
rect.P1 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), rect.P1.Y);
rect.P2 = new UnitPoint(Math.Min(startPoint.X, endPoint.X), rect.P2.Y);
} else if (pointid == ePoint.P23) {
startPoint = rect.P41;
rect.P2 = new UnitPoint(rect.P2.X, Math.Min(startPoint.Y, endPoint.Y));
rect.P3 = new UnitPoint(rect.P3.X, Math.Min(startPoint.Y, endPoint.Y));
} else if (pointid == ePoint.P34) {
startPoint = rect.P12;
rect.P3 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), rect.P3.Y);
rect.P4 = new UnitPoint(Math.Max(startPoint.X, endPoint.X), rect.P4.Y);
} else if (pointid == ePoint.P41) {
startPoint = rect.P23;
rect.P1 = new UnitPoint(rect.P1.X, Math.Max(startPoint.Y, endPoint.Y));
rect.P4 = new UnitPoint(rect.P4.X, Math.Max(startPoint.Y, endPoint.Y));
}
} else if (pointid == ePoint.Center) {
rect.Center = endPoint;
}
}
}
}