using AI.Common.Tools;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
namespace AI.Reconstruction
{
///重要说明: 项目开发时使用的AI.Common(1.0.1.22)、AI.DiagSystem(1.0.1.31) 均为老版本
///现替换为正式发布的Release版AI.Common(1.0.1.31)、AI.DiagSystem(1.0.1.44),
///但与之前版本比较,缺少Point3DF、Point2DF等结构体定义,所以在此临时添加接口
///等添加接口后,仍需改为release版
///
/// 2维点坐标
/// 代替System.Drawing.Point
///
[DataContract]
[StructLayout(LayoutKind.Sequential)]
public struct Point2DF : IEquatable
{
private float _x;
private float _y;
///
/// X坐标
///
[DataMember]
public float X { get => _x; set => _x = value; }
///
/// Y坐标
///
[DataMember]
public float Y { get => _y; set => _y = value; }
///
/// 构造函数
///
///
///
public Point2DF(float x, float y)
{
_x = x;
_y = y;
}
///
/// 空的点
///
public static readonly Point2DF Empty = new Point2DF(0, 0);
///
/// 判断是否相等
///
///
///
public bool Equals(Point2DF other)
{
return Equals(this, other);
}
///
/// 判断是否相等
///
///
///
public override bool Equals(object obj)
{
if (obj == null || !(obj is Point2DF))
{
return false;
}
Point2DF point = (Point2DF)obj;
return Equals(this, point);
}
///
/// 获得哈希值
///
///
public override int GetHashCode()
{
return string.Format("{0}-{1}", _x, _y).GetHashCode();
}
///
/// 转成字符串
///
///
public override string ToString()
{
return SerializeDeserializeHelper.SerializeToJsonString(this);
}
///
/// 从字符串中重建
///
///
///
public static Point2DF FromString(string str)
{
return SerializeDeserializeHelper.DeserializeJsonResult(str);
}
///
/// 转为bytes
///
///
public byte[] ToBytes()
{
byte[] result;
using (var stream = new MemoryStream())
{
var writer = new AIStreamWriter(stream);
writer.WriteFloat(_x);
writer.WriteFloat(_y);
result = stream.ToArray();
}
return result;
}
///
/// 从bytes里重建
///
///
///
public static Point2DF FromBytes(byte[] bytes)
{
Point2DF result;
using (var stream = new MemoryStream(bytes))
{
stream.Position = 0;
var reader = new AIStreamReader(stream);
var x = reader.ReadFloat();
var y = reader.ReadFloat();
result = new Point2DF(x, y);
}
return result;
}
public static bool Equals(Point2DF one, Point2DF other)
{
return one.X == other.X && one.Y == other.Y;
}
public static bool operator ==(Point2DF left, Point2DF right)
{
return Equals(left, right);
}
public static bool operator !=(Point2DF left, Point2DF right)
{
return !Equals(left, right);
}
///
/// 计算两点之间的距离
///
///
///
///
public static float Distance(Point2DF one, Point2DF other)
{
return (float)Math.Sqrt(Math.Pow(one.X - other.X, 2) + Math.Pow(one.Y - other.Y, 2));
}
///
/// 求两点之间的中点
///
///
///
///
public static Point2DF MidPoint(Point2DF one, Point2DF other)
{
return new Point2DF((one.X + other.X) / 2, (one.Y + other.Y) / 2);
}
}
///
/// 3维点坐标
///
[DataContract]
[StructLayout(LayoutKind.Sequential)]
public struct Point3DF : IEquatable
{
private float _x;
private float _y;
private float _z;
///
/// X坐标
///
[DataMember]
public float X { get => _x; set => _x = value; }
///
/// Y坐标
///
[DataMember]
public float Y { get => _y; set => _y = value; }
///
/// Z坐标
///
[DataMember]
public float Z { get => _z; set => _z = value; }
///
/// 构造函数
///
///
///
///
public Point3DF(float x, float y, float z)
{
_x = x;
_y = y;
_z = z;
}
///
/// 空的点
///
public static readonly Point3DF Empty = new Point3DF(0, 0, 0);
///
/// 判断是否相等
///
///
///
public bool Equals(Point3DF other)
{
return Equals(this, other);
}
///
/// 判断是否相等
///
///
///
public override bool Equals(object obj)
{
if (obj == null || !(obj is Point3DF))
{
return false;
}
Point3DF point = (Point3DF)obj;
return Equals(this, point);
}
///
/// 获取哈希值
///
///
public override int GetHashCode()
{
return string.Format("{0}-{1}-{2}", _x, _y, _z).GetHashCode();
}
///
/// 转成字符串
///
///
public override string ToString()
{
return SerializeDeserializeHelper.SerializeToJsonString(this);
}
///
/// 从字符串中生成
///
///
///
public Point3DF FromString(string str)
{
return SerializeDeserializeHelper.DeserializeJsonResult(str);
}
///
/// 转为bytes
///
///
public byte[] ToBytes()
{
byte[] result;
using (var stream = new MemoryStream())
{
var writer = new AIStreamWriter(stream);
writer.WriteFloat(_x);
writer.WriteFloat(_y);
writer.WriteFloat(_z);
result = stream.ToArray();
}
return result;
}
///
/// 从bytes里重建
///
///
///
public static Point3DF FromBytes(byte[] bytes)
{
Point3DF result;
using (var stream = new MemoryStream(bytes))
{
stream.Position = 0;
var reader = new AIStreamReader(stream);
var x = reader.ReadFloat();
var y = reader.ReadFloat();
var z = reader.ReadFloat();
result = new Point3DF(x, y, z);
}
return result;
}
public static bool Equals(Point3DF one, Point3DF other)
{
return one.X == other.X && one.Y == other.Y && one.Z == other.Z;
}
public static bool operator ==(Point3DF left, Point3DF right)
{
return Equals(left, right);
}
public static bool operator !=(Point3DF left, Point3DF right)
{
return !Equals(left, right);
}
public static float Distance(Point3DF one, Point3DF other)
{
return (float)Math.Sqrt(Math.Pow(one.X - other.X, 2) + Math.Pow(one.Y - other.Y, 2) + Math.Pow(one.Z - other.Z, 2));
}
}
///
/// 矩形框
/// 代替System.Drawing.Rectangle
///
[DataContract]
public struct RectF : IEquatable
{
private float _left;
private float _top;
private float _right;
private float _bottom;
private float _width;
private float _height;
///
/// 面积
///
public float Area
{
get => _width * _height;
}
///
/// 右
///
public float Right { get => _right; }
///
/// 下
///
public float Bottom { get => _bottom; }
///
/// 左
///
[DataMember]
public float Left
{
get => _left;
set { _left = value; _right = _left + _width; }
}
///
/// 上
///
[DataMember]
public float Top
{
get => _top;
set { _top = value; _bottom = _top + _height; }
}
///
/// 宽度
///
[DataMember]
public float Width
{
get => _width;
set
{
if (value < 0)
{
throw new ArgumentException("width", "Width should be greater than 0.");
};
_width = value;
_right = _left + _width;
}
}
///
/// 高度
///
[DataMember]
public float Height
{
get => _height;
set
{
if (value < 0)
{
throw new ArgumentException("height", "Height should be greater than 0");
};
_height = value;
_bottom = _top + _height;
}
}
///
/// 构造函数
///
///
///
///
///
public RectF(float left, float top, float width, float height)
{
if (width < 0)
{
throw new ArgumentException("width", "Width should be greater than 0.");
}
if (height < 0)
{
throw new ArgumentException("height", "Height should be greater than 0");
}
_left = left;
_top = top;
_width = width;
_height = height;
_right = left + width;
_bottom = top + height;
}
///
/// 判断是否为未被初始化的Rect结构
///
///
public bool IsEmpty()
{
return Equals(this, Empty);
}
///
/// 空矩形框
///
public static readonly RectF Empty = new RectF(0, 0, 0, 0);
///
/// 判断是否相等
///
///
///
public bool Equals(RectF rect)
{
return Equals(this, rect);
}
///
/// 判断是否相等
///
///
///
public override bool Equals(object obj)
{
if (obj == null || !(obj is RectF))
{
return false;
}
RectF point = (RectF)obj;
return Equals(this, point);
}
///
/// 获得哈希值
///
///
public override int GetHashCode()
{
return string.Format("{0}-{1}-{2}-{3}", _left, _right, _width, _height).GetHashCode();
}
///
/// 转成字符串
///
///
public override string ToString()
{
return SerializeDeserializeHelper.SerializeToJsonString(this);
}
///
/// 从字符串中生成
///
///
///
public static RectF FromString(string str)
{
return SerializeDeserializeHelper.DeserializeJsonResult(str);
}
///
/// 转为bytes
///
///
public byte[] ToBytes()
{
byte[] result;
using (var stream = new MemoryStream())
{
var writer = new AIStreamWriter(stream);
writer.WriteFloat(_left);
writer.WriteFloat(_top);
writer.WriteFloat(_width);
writer.WriteFloat(_height);
result = stream.ToArray();
}
return result;
}
///
/// 从bytes里重建
///
///
///
public static RectF FromBytes(byte[] bytes)
{
RectF result;
using (var stream = new MemoryStream(bytes))
{
stream.Position = 0;
var reader = new AIStreamReader(stream);
var left = reader.ReadFloat();
var top = reader.ReadFloat();
var width = reader.ReadFloat();
var height = reader.ReadFloat();
result = new RectF(left, top, width, height);
}
return result;
}
public static bool Equals(RectF one, RectF other)
{
return one.Left == other.Left && one.Top == other.Top && one.Width == other.Width && one.Height == other.Height;
}
public static bool operator ==(RectF left, RectF right)
{
return Equals(left, right);
}
public static bool operator !=(RectF left, RectF right)
{
return !Equals(left, right);
}
///
/// 在原来的rect的基础上,上下左右一起偏移指定像素数
/// 当offset为正时,为一起向正方向偏移(向右或向下)
/// 当offset为负时,为一起向负方向偏移(向左或向上)
///
///
///
///
public static RectF Offset(RectF rect, float offsetX, float offsetY)
{
return new RectF(rect.Left + offsetX, rect.Top + offsetY, rect.Width, rect.Height);
}
///
/// 以原来的rect中心为中心,上下左右一起向外扩张或内缩指定像素数
/// 当offset为正时,为外扩,当offset为负时,为内缩
///
///
///
///
public static RectF AdjustRect(RectF rect, float offsetX, float offsetY)
{
// 往内缩时,不能缩成负的了
if (offsetX < -rect.Width / 2)
{
offsetX = -rect.Width / 2;
}
if (offsetY < -rect.Height / 2)
{
offsetY = -rect.Height / 2;
}
var correctedLeft = rect.Left - offsetX;
var correctedRight = rect.Right + offsetX;
var correctedTop = rect.Top - offsetY;
var correctedBottom = rect.Bottom + offsetY;
var correctedWidth = correctedRight - correctedLeft;
var correctedHeight = correctedBottom - correctedTop;
return new RectF(correctedLeft, correctedTop, correctedWidth, correctedHeight);
}
///
/// 以clipBound为边界,截断当前rect
/// 即,左上右下角,改为不超过clipBound所限定的范围
///
///
///
///
public static RectF Clip(RectF rect, RectF clipBound)
{
var left = Math.Min(Math.Max(rect.Left, clipBound.Left), clipBound.Right);
var right = Math.Min(Math.Max(rect.Right, clipBound.Left), clipBound.Right);
var top = Math.Min(Math.Max(rect.Top, clipBound.Top), clipBound.Bottom);
var bottom = Math.Min(Math.Max(rect.Bottom, clipBound.Top), clipBound.Bottom);
var width = right - left;
var height = bottom - top;
return new RectF(left, top, width, height);
}
///
/// 计算两个rect的相交部分
///
///
///
///
public static RectF Intersection(RectF a, RectF b)
{
var left = Math.Max(a.Left, b.Left);
var top = Math.Max(a.Top, b.Top);
var right = Math.Min(a.Right, b.Right);
var bottom = Math.Min(a.Bottom, b.Bottom);
if (left > right || top > bottom)
{
return RectF.Empty;
}
var width = right - left;
var height = bottom - top;
return new RectF(left, top, width, height);
}
///
/// 计算两个rect的并集
///
///
///
///
public static RectF Union(RectF a, RectF b)
{
var left = Math.Min(a.Left, b.Left);
var top = Math.Min(a.Top, b.Top);
var right = Math.Max(a.Right, b.Right);
var bottom = Math.Max(a.Bottom, b.Bottom);
var width = right - left;
var height = bottom - top;
return new RectF(left, top, width, height);
}
///
/// 计算两个rect的IOU
/// 注意:计算IOU时,分子是a和b的交集的面积(= Intersect(a,b).Area)
/// 分母是a和b的并集的面积(≠Union(a,b).Area,而应该是a.Area+b.Area-Intersection(a,b).Area)
///
///
///
///
public static float CalcIOU(RectF a, RectF b)
{
var intersection = Intersection(a, b);
var areaInter = intersection.Area;
var areaUnion = a.Area + b.Area - areaInter;
if (areaUnion <= 0)
{
return 0;
}
else
{
return areaInter * 1.0f / areaUnion;
}
}
}
}