Добавьте файлы проекта.

This commit is contained in:
palex
2026-01-06 02:07:18 +03:00
parent 153b9675e3
commit 8e4b375e80
109 changed files with 10817 additions and 0 deletions

31
Geometry/BoundingBox2d.cs Normal file
View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class BoundingBox2d
{
Point2d min;
Point2d max;
public Point2d Min { get => min; private set => min = value; }
public Point2d Max { get => max; private set => max = value; }
public BoundingBox2d()
{
min = new Point2d();
max = new Point2d();
}
public BoundingBox2d(Point2d minPt, Point2d maxPt)
{
min = minPt;
max = maxPt;
}
}
}

9
Geometry/IVector.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace Geo
{
public interface IVector
{
int N { get; }
double[] ToArray();
}
}

96
Geometry/Line2d.cs Normal file
View File

@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Line2d
{
protected Point3d startPoint;
protected Point3d endPoint;
protected Vector2d directive;
protected Vector2d normal;
public Point3d StartPoint { get => startPoint; set { startPoint = value; if (EndPoint != null) { directive = endPoint.ToPoint2d() - startPoint.ToPoint2d(); CalcLine(); }; } }
public Point3d EndPoint { get => endPoint; set { endPoint = value; directive = endPoint.ToPoint2d() - startPoint.ToPoint2d(); CalcLine(); } }
public Point3d CenterPoint { get; private set; }
public Vector2d Directive { get => directive; private set => directive = value; }
public Vector2d Normal { get => normal; private set => normal = value; }
public double A { get; private set; }
public double B { get; private set; }
public double C { get; private set; }
public double k { get; private set; }
public double b { get; private set; }
public double Length { get => Directive.Norma; }
public double cosAlfa { get; private set; }
public double cosBeta { get; private set; }
public double p { get; private set; }
public Line2d()
{
}
public Line2d(Point2d startPt, Point2d endPt)
{
startPoint = startPt.ToPoint3d(); endPoint = endPt.ToPoint3d();
directive = endPoint.ToPoint2d() - startPoint.ToPoint2d();
CalcLine();
}
public Line2d(Point3d startPt, Point3d endPt)
{
startPoint = startPt;
endPoint = endPt;
directive = endPoint.ToPoint2d() - startPoint.ToPoint2d();
CalcLine();
}
protected void CalcLine()
{
A = Directive.Vy;
B = -Directive.Vx;
normal = new Vector2d(A, B);
C = Directive.Vx * StartPoint.Y - Directive.Vy * StartPoint.X;
if (Directive.Vx != 0) { k = Directive.Vy / Directive.Vx; }
else { k = Double.PositiveInfinity; }
if (Directive.Vx != 0) { b = -Directive.Vy / Directive.Vx * StartPoint.X + StartPoint.Y; }
else { b= Double.PositiveInfinity; }
double normC = 1 / Math.Sqrt(A * A + B * B);
if (C < 0) normC *= -1;
cosAlfa = A * normC;
cosBeta = B * normC;
p = C * normC;
double dx = 0.5 * (EndPoint.X - StartPoint.X);
double dy = 0.5 * (EndPoint.Y - StartPoint.Y);
CenterPoint = new Point3d(StartPoint.X + dx, StartPoint.Y + dy, 0);
}
public double LengthTo(Point2d point)
{
double normC = 1 / Math.Sqrt(A * A + B * B);
if (C < 0) normC *= -1;
cosAlfa = A * normC;
cosBeta = B * normC;
p = C * normC;
return normC * (A * point.X + B * point.Y + C);
}
public double LengthTo(Point3d point)
{
double normC = 1 / Math.Sqrt(A * A + B * B);
if (C < 0) normC *= -1;
cosAlfa = A * normC;
cosBeta = B * normC;
p = C * normC;
return normC * (A * point.X + B * point.Y + C);
}
public double Interpolation(double x)
{
if (B == 0) return double.PositiveInfinity;
else return (-A * x - C) / B;
}
}
}

37
Geometry/Line3d.cs Normal file
View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Line3d
{
Point3d startPoint;
Point3d endPoint;
public Point3d StartPoint { get => startPoint; set { startPoint = value; Directive = endPoint - startPoint; } }
public Point3d EndPoint { get => endPoint; set { endPoint = value; Directive = endPoint - startPoint; } }
public Vector3d Directive { get; private set; }
public double Length { get => Directive.Norma; }
public Line3d()
{
}
public Line3d(Point2d startPt, Point2d endPt)
{
startPoint = startPt.ToPoint3d(); endPoint = endPt.ToPoint3d();
Directive = endPoint - startPoint; ;
}
public Line3d(Point3d startPt, Point3d endPt)
{
startPoint = startPt; endPoint = endPt;
Directive = endPoint - startPoint; ;
}
}
}

200
Geometry/Matrix.cs Normal file
View File

@@ -0,0 +1,200 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Matrix
{
double[,] arr;
int m, n;
public int N
{
get
{
if (n > 0)
return n;
else
return -1;
}
}
public int M
{
get
{
if (m > 0)
return m;
else
return -1;
}
}
public double this[int i, int j]
{
get
{
if (n > 0 && m > 0)
if (i > -1 && j > -1)
return arr[i, j];
else
Console.WriteLine("Неверный индексы");
else
Console.WriteLine("Не задана матрица");
return -1;
}
set
{
if (n > 0 && m > 0)
if (i > -1 && j > -1)
arr[i, j] = value;
else
Console.WriteLine("Неверный индексы");
else
Console.WriteLine("Не задана матрица");
}
}
public Matrix(int N, int M)
{
m = M;
n = N;
arr = new double[N, M];
}
public Matrix(Matrix source)
{
m = source.M;
n = source.N;
arr = new double[source.N, source.M];
arr = (double[,])source.arr.Clone();
}
public Matrix(double[,] source)
{
m = source.GetLength(1);
n = source.GetLength(0);
arr = new double[source.GetLength(0), source.GetLength(1)];
arr = (double[,])source.Clone();
}
public double[,] ToArray()
{
return arr;
}
public Matrix Copy()
{
return new Matrix(this);
}
public static Matrix operator ^(Matrix A, Matrix B)
{
if (A.M != B.N) { throw new System.ArgumentException("Не совпадают размерности матриц"); } //Нужно только одно соответствие
Matrix C = new Matrix(A.N, B.M); //Столько же строк, сколько в А; столько столбцов, сколько в B
for (int i = 0; i < A.N; ++i)
{
for (int j = 0; j < B.M; ++j)
{
C[i, j] = 0;
for (int k = 0; k < A.M; ++k)
{ //ТРЕТИЙ цикл, до A.m=B.n
C[i, j] += A[i, k] * B[k, j]; //Собираем сумму произведений
}
}
}
return C;
}
public static Matrix operator *(Matrix A, Matrix B)
{
if (((A.n != B.n) || (A.m != B.m)) == true) { throw new System.ArgumentException("Не совпадают размерности матриц"); }
double[,] res = new double[A.n, B.m];
for (int i = 0; i < A.n; i++)
{
for (int j = 0; j < B.m; j++)
{
res[i, j] = A[i, j] * B[i, j];
}
}
return new Matrix(res);
}
public static Vector operator *(Matrix A, Vector B)
{
if (A.M != B.N) { throw new System.ArgumentException("Не совпадают размерности матриц"); }
double[] res = new double[A.N];
for (int i = 0; i < A.N; i++)
{
for (int j = 0; j < B.N; j++)
{
res[i] += A[i, j] * B[j];
}
}
return new Vector(res);
}
public static Vector3d operator *(Matrix A, Vector3d B)
{
if (A.n != 3 && A.m != 3) { throw new System.ArgumentException("Не верна размерность матрицы"); }
double[] res = new double[3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
res[i] += A[i, j] * B[j];
}
}
return new Vector3d (res);
}
public static Point3d operator *(Matrix A, Point3d B)
{
if (A.n != 3 && A.m != 3) { throw new System.ArgumentException("Не верна размерность матрицы"); }
double[] res = new double[3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
res[i] += A[i, j] * B[j];
}
}
return new Point3d(res);
}
public static Matrix operator *(Matrix A, double B)
{
double[,] res = new double[A.n, A.m];
for (int i = 0; i < A.n; i++)
{
for (int j = 0; j < A.m; j++)
{
res[i, j] = A[i, j] * B;
}
}
return new Matrix(res);
}
public static Matrix operator +(Matrix A, Matrix B)
{
if (((A.n != B.n) || (A.m != B.m)) == true) { throw new System.ArgumentException("Не совпадают размерности матриц"); }
double[,] res = new double[A.n, B.m];
for (int i = 0; i < A.n; i++)
{
for (int j = 0; j < B.m; j++)
{
res[i, j] = A[i, j] + B[i, j];
}
}
return new Matrix(res);
}
}
}

242
Geometry/Plane.cs Normal file
View File

@@ -0,0 +1,242 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Math;
namespace Geo
{
[Serializable]
public class Plane
{
double a;
double b;
double c;
double d;
double gammaRad;
double gammaDeg;
public double A { get => a; set { a = value; CalcPlane(); } }
public double B { get => b; set { b = value; CalcPlane(); } }
public double C { get => c; set { c = value; CalcPlane(); } }
public double D { get => d; set { d = value; CalcPlane(); } }
public double AlfaRad { get; private set; }
public double BetaRad { get; private set; }
public double GammaRad { get => gammaRad; set { gammaRad = value; RadToDeg(); } }
public double AlfaDeg { get; private set; }
public double BetaDeg { get; private set; }
public double GammaDeg { get => gammaDeg; set { gammaDeg = value; DegToRad(); } }
public Matrix MrAlfa { get; private set; }
public Matrix MrBeta { get; private set; }
public Matrix MrGamma { get; private set; }
public Vector3d X1 { get; private set; }
public Vector3d Y1 { get; private set; }
public Vector3d Z1 { get; private set; }
public Vector3d Normal { get; private set; }
public Matrix Mr { get; private set; }
public Point3d Basis { get; set; }
public Plane()
{
Basis = new Point3d() { X = 0, Y = 0, Z = 0 };
a = 0;
b = 0;
c = 1;
d = 0;
CalcPlane();
}
public Plane(Point3d pt1, Point3d pt2, Point3d pt3)
{
Basis = pt1;
Vector3d v1 = new Vector3d()
{
Vx = pt2.X - pt1.X,
Vy = pt2.Y - pt1.Y,
Vz = pt2.Z - pt1.Z
};
Vector3d v2 = new Vector3d()
{
Vx = pt3.X - pt1.X,
Vy = pt3.Y - pt1.Y,
Vz = pt3.Z - pt1.Z
};
a = v1.Vy * v2.Vz - v1.Vz * v2.Vy;
b = v1.Vz * v2.Vx - v1.Vx * v2.Vz;
c = v1.Vx * v2.Vy - v1.Vy * v2.Vx;
d = -a * pt1.X - b * pt1.Y - c * pt1.Z;
CalcPlane();
RadToDeg();
}
public Plane(Point3d pt1, Point3d pt2, Point3d pt3, Point3d bpt)
{
Basis = bpt;
Vector3d v1 = new Vector3d()
{
Vx = pt2.X - pt1.X,
Vy = pt2.Y - pt1.Y,
Vz = pt2.Z - pt1.Z
};
Vector3d v2 = new Vector3d()
{
Vx = pt3.X - pt1.X,
Vy = pt3.Y - pt1.Y,
Vz = pt3.Z - pt1.Z
};
a = v1.Vy * v2.Vz - v1.Vz * v2.Vy;
b = v1.Vz * v2.Vx - v1.Vx * v2.Vz;
c = v1.Vx * v2.Vy - v1.Vy * v2.Vx;
d = -a * pt1.X - b * pt1.Y - c * pt1.Z;
CalcPlane();
RadToDeg();
}
public double Interpolation(double x, double y)
{
if (C == 0) return double.PositiveInfinity;
else return (-A * x - B * y - D) / C;
}
protected void CreatePlane(Point3d pt1, Point3d pt2, Point3d pt3)
{
Basis = pt1;
Vector3d v1 = new Vector3d()
{
Vx = pt2.X - pt1.X,
Vy = pt2.Y - pt1.Y,
Vz = pt2.Z - pt1.Z
};
Vector3d v2 = new Vector3d()
{
Vx = pt3.X - pt1.X,
Vy = pt3.Y - pt1.Y,
Vz = pt3.Z - pt1.Z
};
a = v1.Vy * v2.Vz - v1.Vz * v2.Vy;
b = v1.Vz * v2.Vx - v1.Vx * v2.Vz;
c = v1.Vx * v2.Vy - v1.Vy * v2.Vx;
d = -a * pt1.X - b * pt1.Y - c * pt1.Z;
CalcPlane();
RadToDeg();
}
protected void CalcPlane()
{
Normal = new Vector3d
{
Vx = a,
Vy = b,
Vz = c
};
Intersect();
CreateMatrix();
}
protected void Intersect()
{
if ((a == 0 & b == 0) == false)
{
Vector3d v3 = new Vector3d { Vx = 0, Vy = 0, Vz = 1 };
Z1 = new Vector3d(Normal.Unit);
X1 = new Vector3d((v3 ^ Z1).Unit);
Y1 = new Vector3d((Z1 ^ X1).Unit);
AlfaRad = -Acos(X1.Vx);
BetaRad = -Acos(Z1.Vz);
//alfaRad = Math.Acos(unitP.Vx);
//betaRad = Math.Acos(unitNormal.Vz);
}
}
protected void CreateMatrix()
{
Vector3d o = new Vector3d();
o[0] = -X1.Vx * Basis.X - X1.Vy * Basis.Y - X1.Vz * Basis.Z;
o[1] = -Y1.Vx * Basis.X - Y1.Vy * Basis.Y - Y1.Vz * Basis.Z;
o[2] = -Z1.Vx * Basis.X - Z1.Vy * Basis.Y - Z1.Vz * Basis.Z;
Mr = new Matrix(4, 4);
Mr[0, 0] = X1.Vx; Mr[0, 1] = X1.Vy; Mr[0, 2] = X1.Vz; Mr[0, 3] = o.Vx;
Mr[1, 0] = Y1.Vx; Mr[1, 1] = Y1.Vy; Mr[1, 2] = Y1.Vz; Mr[1, 3] = o.Vy;
Mr[2, 0] = Z1.Vx; Mr[2, 1] = Z1.Vy; Mr[2, 2] = Z1.Vz; Mr[2, 3] = o.Vz;
Mr[3, 0] = 0; Mr[3, 1] = 0; Mr[3, 2] = 0; Mr[3, 3] = 1;
MrAlfa = new Matrix(3, 3);
MrAlfa[0, 0] = Cos(AlfaRad); MrAlfa[0, 1] = -Sin(AlfaRad); MrAlfa[0, 2] = 0;
MrAlfa[1, 0] = Sin(AlfaRad); MrAlfa[1, 1] = Cos(AlfaRad); MrAlfa[1, 2] = 0;
MrAlfa[2, 0] = 0; MrAlfa[2, 1] = 0; MrAlfa[2, 2] = 0;
MrBeta = new Matrix(3, 3);
MrBeta[0, 0] = 1; MrBeta[0, 1] = 0; MrBeta[0, 2] = 0;
MrBeta[1, 0] = 0; MrBeta[1, 1] = Cos(BetaRad); MrBeta[1, 2] = -Sin(BetaRad);
MrBeta[2, 0] = 0; MrBeta[2, 1] = Sin(BetaRad); MrBeta[2, 2] = Cos(BetaRad);
MrGamma = new Matrix(3, 3);
MrGamma[0, 0] = Cos(gammaRad); MrGamma[0, 1] = -Sin(gammaRad); MrGamma[0, 2] = 0;
MrGamma[1, 0] = Sin(gammaRad); MrGamma[1, 1] = Cos(gammaRad); MrGamma[1, 2] = 0;
MrGamma[2, 0] = 0; MrGamma[2, 1] = 0; MrGamma[2, 2] = 1;
}
public Point3d PointInLCS(Point3d pt)
{
double[] d1 = new double[] { 0, 0, 0, 1 }; ;
Vector v1 = new Vector(d1);
v1[0] = pt.X; v1[1] = pt.Y; v1[2] = pt.Z;
return new Point3d().FromArray((Mr * v1).ToArray());
}
protected double[] MultiplyMtxVec(double[,] _Matrix, double[] _Vector)
{
int n = _Vector.Length;
double[] _Result = new double[n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
_Result[i] += _Matrix[i, j] * _Vector[j];
}
}
return _Result;
}
protected void RadToDeg()
{
AlfaDeg = AlfaRad * 180 / PI;
BetaDeg = BetaRad * 180 / PI;
gammaDeg = gammaRad * 180 / PI;
}
protected void DegToRad()
{
gammaRad = gammaDeg * 180 / PI;
}
}
}

120
Geometry/Point2d.cs Normal file
View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Point2d
{
double[] arr = new double[2];
public double this[int i] { get => arr[i]; set => arr[i] = value; }
public double X { get => arr[0]; set => arr[0] = value; }
public double Y { get => arr[1]; set => arr[1] = value; }
public Point2d()
{
arr = new double[2];
}
public Point2d(double x, double y)
{
arr = new double[2];
arr[0] = x; arr[1] = y;
}
public Point2d(Point2d source)
{
arr = new double[2];
arr = (double[])source.arr.Clone();
}
public Point2d(Point3d source)
{
arr = new double[2];
arr[0]=source.X; arr[1] = source.Y;
}
public Point2d(double[] source)
{
arr = new double[2];
if (source.Length >= 2)
{
arr[0] = source[0]; arr[1] = source[1];
}
}
public double[] ToArray()
{
return new double[] { X, Y };
}
public Vector2d ToVector2d()
{
return new Vector2d { Vx = X, Vy = Y};
}
public Vector3d ToVector3d()
{
return new Vector3d { Vx = X, Vy = Y, Vz = 0 };
}
public Point3d ToPoint3d()
{
return new Point3d { X = X, Y = Y, Z = 0 };
}
public Point2d FromArray(double[] arr)
{
X = arr[0]; Y = arr[1];
return this;
}
public double LengthTo(Point2d node)
{
Line2d line = new Line2d(this, node);
return line.Length;
}
public static Vector2d operator -(Point2d pt1, Point2d pt2)
{
Vector2d res = new Vector2d();
res[0] = pt1.X - pt2.X;
res[1] = pt1.Y - pt2.Y;
return res;
}
public static bool operator ==(Point2d p1, Point2d p2)
{
bool check = false;
if (p1.X == p2.X && p1.Y == p2.Y)
{
check = true;
}
return (check);
}
public static bool operator !=(Point2d p1, Point2d p2)
{
bool check = true;
if (p1.X == p2.X && p1.Y == p2.Y)
{
check = false;
}
return (check);
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

156
Geometry/Point3d.cs Normal file
View File

@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Point3d : IVector
{
double[] arr;
//int n = 3;
public double this[int i] { get => arr[i]; set => arr[i] = value; }
public double X { get => arr[0]; set => arr[0] = value; }
public double Y { get => arr[1]; set => arr[1] = value; }
public double Z { get => arr[2]; set => arr[2] = value; }
public int N => 3;
//int N { get => n; }
public Point3d()
{
arr = new double[3];
}
public Point3d(double x, double y, double z)
{
arr = new double[3];
arr[0] = x; arr[1] = y; arr[2] = z;
}
public Point3d(double x, double y)
{
arr = new double[3];
arr[0] = x; arr[1] = y; arr[2] = 0;
}
public Point3d(Point3d source)
{
arr = new double[3];
arr = (double[])source.arr.Clone();
}
public Point3d(double[] source)
{
arr = new double[3];
if (source.Length >= 3) { arr[0] = source[0]; arr[1] = source[1]; arr[2] = source[2]; }
else if (source.Length == 2) { arr[0] = source[0]; arr[1] = source[1]; }
else { arr[0] = source[0]; }
}
public double[] ToArray()
{
return new double[] { X, Y, Z };
}
public Vector3d ToVector3d()
{
return new Vector3d { Vx = X, Vy = Y, Vz = Z };
}
public Point2d ToPoint2d()
{
return new Point2d { X = X, Y = Y };
}
public Point3d FromArray(double[] arr)
{
X = arr[0]; Y = arr[1]; Z = arr[2];
return this;
}
public double LengthTo(Point3d node)
{
Line3d line = new Line3d(this, node);
return line.Length;
}
public double AngleTo(Point3d startPoint, Point3d endPoint)
{
Point3d tempNode = new Point3d();
Line3d tempLine1 = new Line3d(this, startPoint);
Line3d tempLine2 = new Line3d(this, endPoint);
double cosTo = Vector3d.CosAngleBetVectors(tempLine1.Directive, tempLine2.Directive);
return RadToDeg(Math.Acos(cosTo));
}
public bool NormalDirection(Point3d startNode, Point3d endNode)
{
Line3d tempLine1 = new Line3d(this, startNode);
Line3d tempLine2 = new Line3d(this, endNode);
double norm = (tempLine1.Directive ^ tempLine2.Directive).Vz;
bool res = false;
if (norm > 0) res = true;
return res;
}
private double RadToDeg(double radians)
{
return radians * 180 / Math.PI;
}
public static Point3d operator *(Point3d pt, double prime)
{
return new Point3d
{
X = pt.X * prime,
Y = pt.Y * prime,
Z = pt.Z * prime
};
}
public static Vector3d operator -(Point3d pt1, Point3d pt2)
{
Vector3d res = new Vector3d();
res[0] = pt1.X - pt2.X;
res[1] = pt1.Y - pt2.Y;
res[2] = pt1.Z - pt2.Z;
return res;
}
public static bool operator ==(Point3d p1, Point3d p2)
{
bool check = false;
if (p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z)
{
check = true;
}
return (check);
}
public static bool operator !=(Point3d p1, Point3d p2)
{
bool check = true;
if (p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z)
{
check = false;
}
return (check);
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

663
Geometry/Polygon.cs Normal file
View File

@@ -0,0 +1,663 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Polygon
{
private double area;
private double ix;
private double iy;
private List<Point3d> vertices = new List<Point3d>();
public bool Ckw { get; internal set; }
//public bool? IsSelfItersected { get; private set; }
public double Area { get => Math.Abs(area); }
public double Perimeter { get; internal set; }
public Point3d Centroid { get; internal set; }
public double Ix { get => Math.Abs(ix); }
public double Iy { get => Math.Abs(iy); }
public List<Point3d> Vertices { get => vertices; set { vertices = value; CalcPolygon(); } }
public BoundingBox2d BoundingBox { get; internal set; }
public List<Line2d> Segments { get; internal set; }
public Polygon()
{
}
public Polygon(List<Point3d> vrts)
{
vertices = vrts;
if (vertices[0].X != vertices[vrts.Count - 1].X && vertices[0].Y != vertices[vrts.Count - 1].Y) vertices.Add(vertices[0]);
CalcPolygon();
}
public Polygon(List<Point2d> vrts)
{
foreach (Point2d item in vrts) vertices.Add(item.ToPoint3d());
if (vertices[0].X != vertices[vrts.Count - 1].X && vertices[0].Y != vertices[vrts.Count - 1].Y) vertices.Add(vertices[0]);
CalcPolygon();
}
public virtual void AddVertice(Point2d pt)
{
if (vertices.Count == 0)
{
vertices.Add(pt.ToPoint3d());
return;
}
if (vertices.Count == 1)
{
vertices.Add(pt.ToPoint3d());
vertices.Add(vertices[0]);
return;
}
if (vertices.Count >= 3)
{
vertices.RemoveAt(vertices.Count - 1);
vertices.Add(pt.ToPoint3d());
vertices.Add(vertices[0]);
CalcPolygon();
}
}
public virtual void AddVertice(Point3d pt)
{
if (vertices.Count == 0)
{
vertices.Add(pt);
return;
}
if (vertices.Count == 1)
{
vertices.Add(pt);
vertices.Add(vertices[0]);
return;
}
if (vertices.Count >= 3)
{
vertices.RemoveAt(vertices.Count - 1);
vertices.Add(pt);
vertices.Add(vertices[0]);
CalcPolygon();
}
}
private void CalcBB()
{
double minX = 1000000000;
double minY = 1000000000;
double maxX = -1000000000;
double maxY = -1000000000;
if (vertices.Count > 0)
{
foreach (Point3d item in vertices)
{
if (item.X < minX) { minX = item.X; }
if (item.Y < minY) { minY = item.Y; }
if (item.X > maxX) { maxX = item.X; }
if (item.Y > maxY) { maxY = item.Y; }
}
BoundingBox = new BoundingBox2d(new Point2d(minX, minY), new Point2d(maxX, maxY));
}
}
private void CalcSegs()
{
if (vertices.Count > 3)
{
Segments = new List<Line2d>();
for (int i = 0; i < vertices.Count - 1; i++)
{
Segments.Add(new Line2d(vertices[i], vertices[i + 1]));
}
}
}
protected void CalcI()
{
if (Segments.Count > 2)
{
double tempX = 0;
double tempY = 0;
for (int i = 0; i < Segments.Count; i++)
{
Point3d arrTemp = Segments[i].StartPoint; Point3d arrTemp1 = Segments[i].EndPoint;
tempX += (Math.Pow(arrTemp.X, 2) + arrTemp.X * arrTemp1.X + Math.Pow(arrTemp1.X, 2)) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X);
tempY += (Math.Pow(arrTemp.Y, 2) + arrTemp.Y * arrTemp1.Y + Math.Pow(arrTemp1.Y, 2)) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X);
}
ix = tempX / 12;
iy = tempY / 12;
}
}
protected void CalcCentroid()
{
if (Segments.Count > 2)
{
Point3d temp = new Point3d();
for (int i = 0; i < Segments.Count; i++)
{
Point3d arrTemp = Segments[i].StartPoint; Point3d arrTemp1 = Segments[i].EndPoint;
temp.X += 1 / (6 * area) * (arrTemp.X + arrTemp1.X) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X);
temp.Y += 1 / (6 * area) * (arrTemp.Y + arrTemp1.Y) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X);
}
Centroid = temp;
}
}
protected void CalcArea()
{
double temp = 0;
if (Segments.Count > 2)
{
for (int i = 0; i < Segments.Count; i++)
{
Point3d arrTemp = Segments[i].StartPoint; Point3d arrTemp1 = Segments[i].EndPoint;
temp += 0.5 * (arrTemp.X * arrTemp1.Y - arrTemp1.X * arrTemp.Y);
}
area = temp;
}
}
protected void CalcPerimeter()
{
if (Segments.Count > 2)
{
Perimeter = 0;
foreach (Line2d item in Segments)
{
Perimeter += item.Length;
}
}
}
protected void CalcCkw()
{
if (area < 0) Ckw = true;
else Ckw = false;
}
/// <summary>
/// Вычисление свойств полигона
/// </summary>
public void CalcPolygon()
{
if (Vertices.Count > 3)
{
if ((Vertices[0].X != Vertices[vertices.Count - 1].X && Vertices[0].Y != Vertices[Vertices.Count - 1].Y)||
(Vertices[0].X == Vertices[vertices.Count - 1].X && Vertices[0].Y != Vertices[Vertices.Count - 1].Y)||
(Vertices[0].X != Vertices[vertices.Count - 1].X && Vertices[0].Y == Vertices[Vertices.Count - 1].Y))
Vertices.Add(Vertices[0]);
}
CalcBB();
CalcSegs();
CalcPerimeter();
CalcArea();
CalcCkw();
CalcCentroid();
CalcI();
}
/// <summary>
/// Замена вершины полигона
/// </summary>
/// <param name="oldVertIdx">индекс заменяемой вершины</param>
/// <param name="newVert">объект заменяющей вершины</param>
public bool ReplaceVertice( int oldVertIdx, Point3d newVert)
{
try
{
Vertices[oldVertIdx] = newVert;
if (oldVertIdx == 0 || oldVertIdx == Vertices.Count - 1) { Vertices[0] = newVert; Vertices[Vertices.Count - 1] = newVert; }
CalcPolygon();
return true;
}
catch
{
return false;
}
}
public void Triangulation(double shag, out List<Point3d> innerNodes, out List<Triangle> triangles)
{
innerNodes = new List<Point3d>();
triangles = new List<Triangle>();
List<Polygon> polygons = new List<Polygon>();
int n = Tesselation(shag);
Polygon front = new Polygon(Vertices);
//int p = 1;
do
{
if (polygons.Count != 0) { front = polygons[0]; polygons.RemoveAt(0); }
for (int j = 0; j < 1000; j++)
{
AngleIn3Point minAngle;
front.MinAngleDeg(out minAngle);
while (minAngle.AngleDeg == 0 && front.Vertices.Count > 3)
{
if(minAngle.VerticeIdx == 0)
{
front.Vertices.RemoveRange(Vertices.Count - 2, 2);
front.Vertices.RemoveAt(0);
}
else front.Vertices.RemoveRange(minAngle.PreviousIdx, 2);
front.CalcPolygon();
front.MinAngleDeg(out minAngle);
}
if (Math.Round(minAngle.AngleDeg) < 90)
{
triangles.Add(new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx]));
front.Vertices.RemoveAt(minAngle.VerticeIdx);
if (minAngle.VerticeIdx == 0 && front.Vertices.Count > 3) front.Vertices.RemoveAt(front.Vertices.Count - 1);
front.CalcPolygon();
}
else if (Math.Round(minAngle.AngleDeg) == 90 /*&& Math.Round(minAngle.AngleDeg) <= 140*/)
{
Line2d lin = new Line2d(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.PreviousIdx]);
Point3d temp = front.Vertices[minAngle.VerticeIdx];
Point3d g = new Point3d(front.Vertices[minAngle.NextIdx].X + lin.Directive.Vx, front.Vertices[minAngle.NextIdx].Y + lin.Directive.Vy, 0);
Point3d gNode = new Point3d { X = g.X, Y = g.Y, Z = g.Z/*, Number = n*/ };
bool ch = false;
int k = -1;
for (int i = 0; i < front.Vertices.Count - 1; i++)
{
//if (i == minAngle.VerticeIdx) continue;
double d = g.LengthTo(front.Vertices[i]);
if (Math.Round(g.X, 2) == Math.Round(front.Vertices[i].X, 2) && Math.Round(g.Y, 2) == Math.Round(front.Vertices[i].Y, 2))
{ ch = true; k = i; break; }
}
Triangle t1, t2;
if (ch)
{
t1 = new Triangle(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx], front.Vertices[k]);
t2 = new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], front.Vertices[k]);
}
else
{
t1 = new Triangle(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx], gNode);
t2 = new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], gNode);
}
front.ReplaceVertice(minAngle.VerticeIdx, gNode);
if (front.SelfItersectCheck())
{
front.ReplaceVertice(minAngle.VerticeIdx, temp);
double dist = 100000000;
k = -1;
for (int i = 0; i < front.Vertices.Count - 1; i++)
{
if (i == minAngle.NextIdx || i == minAngle.PreviousIdx || i == minAngle.VerticeIdx) continue;
double d = front.Vertices[minAngle.VerticeIdx].LengthTo(front.Vertices[i]);
if (d < dist) { dist = d; k = i; }
}
Polygon sub;
front.Bisection(k, minAngle.VerticeIdx, out sub);
polygons.Add(sub);
}
else
{
if (!ch) { innerNodes.Add(gNode); n++; }
triangles.Add(t1); triangles.Add(t2);
}
}
else
{
Line2d linPrev = new Line2d(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.PreviousIdx]);
Line2d linNext = new Line2d(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx]);
double vx = (linPrev.Directive.Unit[0] + linNext.Directive.Unit[0]) * 0.5;
double vy = (linPrev.Directive.Unit[1] + linNext.Directive.Unit[1]) * 0.5;
//double lengthBis = (linPrev.Length + linNext.Length) * 0.5;
double x = front.Vertices[minAngle.VerticeIdx].X + vx * shag;
double y = front.Vertices[minAngle.VerticeIdx].Y + vy * shag;
Point3d temp = front.Vertices[minAngle.VerticeIdx];
Point3d g = new Point3d(x, y, 0);
Line2d linBis = new Line2d(front.Vertices[minAngle.VerticeIdx], g);
x = front.Vertices[minAngle.VerticeIdx].X + linBis.Directive.Unit[0] * shag;
y = front.Vertices[minAngle.VerticeIdx].Y + linBis.Directive.Unit[1] * shag;
g = new Point3d(x, y, 0);
Point3d gNode = new Point3d() { X = g.X, Y = g.Y, Z = g.Z/*, Number = n*/ };
Triangle t1, t2;
t1 = new Triangle(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx], gNode);
t2 = new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], gNode);
front.ReplaceVertice(minAngle.VerticeIdx, gNode);
//if (p == 1) { Shpunt.AcCreator.CreateContour(front); p++; }
if (front.SelfItersectCheck())
{
front.ReplaceVertice(minAngle.VerticeIdx, temp);
double dist = 100000000;
int k = -1;
for (int i = 0; i < front.Vertices.Count - 1; i++)
{
if (i == minAngle.NextIdx || i == minAngle.PreviousIdx || i == minAngle.VerticeIdx) continue;
double d = front.Vertices[minAngle.VerticeIdx].LengthTo(front.Vertices[i]);
if (d < dist) { dist = d; k = i; }
}
Polygon sub;
front.Bisection(k, minAngle.VerticeIdx, out sub);
polygons.Add(sub);
}
else
{
triangles.Add(t1);
triangles.Add(t2);
innerNodes.Add(gNode);
}
n++;
}
if (front.Vertices.Count < 4) break;
}
} while (polygons.Count != 0);
}
/// <summary>
/// Тесселяция полигона с заданным шагом
/// </summary>
/// <param name="shag"> Величина шага тесселяции</param>
public int Tesselation(double shag)
{
List<Point3d> nodes = new List<Point3d>();
int n = 1;
int nD = 0;
foreach (Line2d seg in Segments)
{
Point3d start = seg.StartPoint;
Point3d end = seg.EndPoint;
nD = (int)Math.Round(seg.Length / shag);
if (nD > 1)
{
double delta = seg.Length / nD;
double deltaX = (end.X - start.X) / nD;
double deltaY = (end.Y - start.Y) / nD;
double deltaZ = (end.Z - start.Z) / nD;
for (int j = 0; j < nD; j++)
{
Point3d pt = new Point3d(start.X + j * deltaX, start.Y + j * deltaY, start.Z + j * deltaZ);
//FEA.Node nd = new FEA.Node(pt) { Number = n };
nodes.Add(pt);
n++;
}
}
else
{
Point3d pt = new Point3d(start.X, start.Y, start.Z);
//FEA.Node nd = new FEA.Node(pt) { Number = n };
nodes.Add(pt);
n++;
}
}
Vertices = nodes;
if (!Ckw) { Vertices.Reverse(); CalcPolygon(); }
return n;
}
/// <summary>
/// Деление полигона через указание 2-х точек деления
/// </summary>
/// <param name="sectPointIdx">Индекс первой точки деления(секущей)</param>
/// <param name="basePointIdx">Индекс второй точки деления(базовой)</param>
/// <param name="newPolygon">Возвращаемый отсеченный полигон</param>
public void Bisection(int sectPointIdx,int basePointIdx, out Polygon newPolygon)
{
newPolygon = new Polygon();
List<Point3d> tmp = new List<Point3d>();
if (basePointIdx > sectPointIdx)
{
for (int i = sectPointIdx; i <= basePointIdx; i++)
{
newPolygon.AddVertice(Vertices[i]);
}
newPolygon.CalcPolygon();
Vertices.RemoveRange(sectPointIdx + 1, basePointIdx - sectPointIdx - 1);
CalcPolygon();
}
else
{
for (int i = basePointIdx; i <= sectPointIdx; i++)
{
newPolygon.AddVertice(Vertices[i]);
}
newPolygon.CalcPolygon();
Vertices.RemoveRange(basePointIdx + 1, sectPointIdx - basePointIdx - 1);
CalcPolygon();
}
}
/// <summary>
/// Проверка полигона на самопересечение (возвращает булево значение, если true - полигон самопересекающийся)
/// </summary>
public bool SelfItersectCheck()
{
bool IsSelfItersected = false;
if (Segments.Count < 4) return IsSelfItersected;
for (int i = 0; i < Segments.Count; i++)
{
for (int j = 0; j < Segments.Count; j++)
{
if (i == j) continue;
double a1 = Segments[i].A;
double a2 = Segments[j].A;
double b1 = Segments[i].B;
double b2 = Segments[j].B;
double c1 = Segments[i].C;
double c2 = Segments[j].C;
double p1 = (b2 - b1 * a2 / a1);
if (p1 == 0) continue;
double y = (a2 * c1 / a1 - c2) / p1;
double x = (-b1 * y - c1) / a1;
Point3d ptItersect = new Point3d(x, y, 0);
Line2d linTmp1 = new Line2d(Segments[i].CenterPoint, ptItersect);
Line2d linTmp2 = new Line2d(Segments[j].CenterPoint, ptItersect);
double l1 = Math.Round(linTmp1.Length, 2);
double l11 = Math.Round(Segments[i].Length / 2, 2);
double l2 = Math.Round(linTmp2.Length, 2);
double l22 = Math.Round(Segments[j].Length / 2, 2);
if (Math.Round(linTmp1.Length, 2) < Math.Round(Segments[i].Length / 2, 2) &&
Math.Round(linTmp2.Length, 2) < Math.Round(Segments[j].Length / 2, 2))
{
IsSelfItersected = true;
return IsSelfItersected;
}
}
}
return IsSelfItersected;
}
/// <summary>
/// Вычисление минимального угла полигона в градусах
/// </summary>
/// <returns></returns>
public double MinAngleDeg()
{
double minAngle = 360;
double angleTmp;
bool type;
for (int i = 0; i < Vertices.Count - 1; i++)
{
if (i == 0)
{
angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[0].NormalDirection(Vertices[Vertices.Count - 2], Vertices[1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp < minAngle) minAngle = angleTmp;
}
else
{
angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp < minAngle) minAngle = angleTmp;
}
}
return minAngle;
}
/// <summary>
/// Вычисление минимального угла полигона в градусах (возвращает массив индексов 3-х точек на которых был найден угол)
/// </summary>
/// <param name="minAngle"> Возвращаемое значение минимального угла в градусах </param>
public int[] MinAngleDeg(out double minAngle)
{
minAngle = 0;
if (Vertices.Count < 3) return null;
int[] res = new int[3];
minAngle = 360;
double angleTmp;
bool type;
for (int i = 0; i < Vertices.Count - 1; i++)
{
if (i == 0)
{
angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[i + 1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[i].NormalDirection(Vertices[Vertices.Count - 2], Vertices[i + 1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp < minAngle)
{
res[0] = Vertices.Count - 2;
res[1] = 0;
res[2] = 1;
minAngle = angleTmp;
}
}
else
{
angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp < minAngle)
{
res[0] = i - 1;
res[1] = i;
res[2] = i + 1;
minAngle = angleTmp;
}
}
}
return res;
}
/// <summary>
/// Вычисление минимального угла полигона в градусах
/// </summary>
/// <param name="result">Возвращаемое значение в виде объекта со свойствами индексов трех точек образуюших угол и значения угла в градусах</param>
public void MinAngleDeg(out AngleIn3Point result)
{
result = new AngleIn3Point();
result.AngleDeg = 0;
if (Vertices.Count < 3) return;
result.AngleDeg = 360;
double angleTmp;
bool type;
for (int i = 0; i < Vertices.Count - 1; i++)
{
if (i == 0)
{
angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[i + 1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[i].NormalDirection(Vertices[Vertices.Count - 2], Vertices[i + 1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp < result.AngleDeg)
{
result.PreviousIdx = Vertices.Count - 2;
result.VerticeIdx = 0;
result.NextIdx = 1;
result.AngleDeg = angleTmp;
}
}
else
{
angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp < result.AngleDeg)
{
result.PreviousIdx = i - 1;
result.VerticeIdx = i;
result.NextIdx = i + 1;
result.AngleDeg = angleTmp;
}
}
}
}
/// <summary>
/// Вычисление максимального угла полигона в градусах
/// </summary>
/// <returns></returns>
public double MaxAngleDeg()
{
double minAngle = 0;
double angleTmp;
bool type;
for (int i = 0; i < Vertices.Count - 1; i++)
{
if (i == 0)
{
angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[i + 1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[i].NormalDirection(Vertices[Vertices.Count - 2], Vertices[i + 1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp > minAngle) minAngle = angleTmp;
}
else
{
angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]);
if (angleTmp is double.NaN) angleTmp = 180;
type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]);
if (!type && angleTmp != 0) angleTmp = 360 - angleTmp;
if (!type && angleTmp == 0) angleTmp = 0;
if (angleTmp > minAngle) minAngle = angleTmp;
}
}
return minAngle;
}
}
/// <summary>
/// Объект-структура со свойствами индексов трех точек образуюших угол и значения угла в градусах
/// </summary>
public struct AngleIn3Point
{
/// <summary>
/// Индекс предыдущей вершины
/// </summary>
public int PreviousIdx { get; set; }
/// <summary>
/// Индех следующей вершины
/// </summary>
public int NextIdx { get; set; }
/// <summary>
/// Индекс вершины, на которой найден угол
/// </summary>
public int VerticeIdx { get; set; }
/// <summary>
/// Значение найденного угла в градусах
/// </summary>
public double AngleDeg { get; set; }
}
}

147
Geometry/Quadrangle.cs Normal file
View File

@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Quadrangle : Polygon
{
private Point3d vertex1 = new Point3d();
private Point3d vertex2 = new Point3d();
private Point3d vertex3 = new Point3d();
private Point3d vertex4 = new Point3d();
public Point3d Vertex1 { get => vertex1; set { vertex1 = value; Vertices[0] = vertex1; CalcQuadrangle(); } }
public Point3d Vertex2 { get => vertex2; set { vertex2 = value; Vertices[1] = vertex2; CalcQuadrangle(); } }
public Point3d Vertex3 { get => vertex3; set { vertex3 = value; Vertices[2] = vertex3; CalcQuadrangle(); } }
public Point3d Vertex4 { get => vertex4; set { vertex4 = value; Vertices[3] = vertex4; CalcQuadrangle(); } }
public double MaxAngleDeg { get; private set; }
public bool IsValid { get; private set; }
public UnitsLin Units { get; set; }
public Quadrangle(Triangle trg1, Triangle trg2)
{
List<Point3d> vrt = new List<Point3d>();
List<Point3d> dgn = new List<Point3d>();
vrt.Add(trg1.Vertex1);
vrt.Add(trg1.Vertex2);
vrt.Add(trg1.Vertex3);
vrt.Add(trg2.Vertex1);
vrt.Add(trg2.Vertex2);
vrt.Add(trg2.Vertex3);
for (int i = 0; i < vrt.Count; i++)
{
for (int j = 0; j < vrt.Count; j++)
{
if (i == j) continue;
if (Math.Round(vrt[i].X, 2) == Math.Round(vrt[j].X,2) && Math.Round(vrt[i].Y,2) == Math.Round(vrt[j].Y,2))
{
dgn.Add(vrt[i]);
vrt.RemoveAt(j);
break;
}
}
}
if (vrt.Count == 4)
{
if (vrt[0].Equals(dgn[0]) && vrt[1].Equals(dgn[1]))
{
vertex1 = vrt[0];
AddVertice(Vertex1);
vertex2 = vrt[2];
AddVertice(Vertex2);
vertex3 = vrt[1];
AddVertice(Vertex3);
vertex4 = vrt[3];
AddVertice(Vertex4);
}
if (vrt[1].Equals(dgn[0]) && vrt[2].Equals(dgn[1]))
{
vertex1 = vrt[0];
AddVertice(Vertex1);
vertex2 = vrt[2];
AddVertice(Vertex2);
vertex3 = vrt[3];
AddVertice(Vertex3);
vertex4 = vrt[1];
AddVertice(Vertex4);
}
if (vrt[0].Equals(dgn[0]) && vrt[2].Equals(dgn[1]))
{
vertex1 = vrt[0];
AddVertice(Vertex1);
vertex2 = vrt[1];
AddVertice(Vertex2);
vertex3 = vrt[2];
AddVertice(Vertex3);
vertex4 = vrt[3];
AddVertice(Vertex4);
}
if (vrt[1].Equals(dgn[0]) && vrt[3].Equals(dgn[1]))
{
vertex1 = vrt[0];
AddVertice(Vertex1);
vertex2 = vrt[1];
AddVertice(Vertex2);
vertex3 = vrt[2];
AddVertice(Vertex3);
vertex4 = vrt[3];
AddVertice(Vertex4);
}
IsValid = true;
CalcQuadrangle();
}
else
{
IsValid = false;
Vertices.Add(new Point3d());
Vertices.Add(new Point3d());
Vertices.Add(new Point3d());
Vertices.Add(new Point3d());
}
}
public Quadrangle(Point3d node1, Point3d node2, Point3d node3, Point3d node4)
{
vertex1 = node1;
AddVertice(node1);
vertex2 = node2;
AddVertice(node2);
vertex3 = node3;
AddVertice(node3);
vertex4 = node4;
AddVertice(node4);
CalcQuadrangle();
IsValid = true;
}
public Quadrangle(Point2d node1, Point2d node2, Point2d node3, Point2d node4)
{
vertex1 = node1.ToPoint3d();
AddVertice(node1);
vertex2 = node2.ToPoint3d();
AddVertice(node2);
vertex3 = node3.ToPoint3d();
AddVertice(node3);
vertex4 = node4.ToPoint3d();
AddVertice(node4);
CalcQuadrangle();
IsValid = true;
}
public void CalcQuadrangle()
{
double ang1, ang2, ang3, ang4;
ang1 = vertex1.AngleTo(vertex4, vertex2);
ang2 = vertex2.AngleTo(vertex1, vertex3);
ang3 = vertex3.AngleTo(vertex2, vertex4);
ang4 = vertex4.AngleTo(vertex3, vertex1);
MaxAngleDeg = Math.Max(Math.Max(Math.Max(ang1, ang2), ang3), ang4);
CalcPolygon();
}
}
}

67
Geometry/Triangle.cs Normal file
View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Triangle : Polygon
{
private Point3d vertex1;
private Point3d vertex2;
private Point3d vertex3;
public Point3d Vertex1 { get => vertex1; set { vertex1 = value; Vertices[0] = vertex1; CalcTriangle(); } }
public Point3d Vertex2 { get => vertex2; set { vertex2 = value; Vertices[1] = vertex2; CalcTriangle(); } }
public Point3d Vertex3 { get => vertex3; set { vertex3 = value; Vertices[2] = vertex3; CalcTriangle(); } }
public double MaxAngleDeg { get; private set; }
public Triangle(Point3d node1, Point3d node2, Point3d node3)
{
vertex1 = node1;
AddVertice(vertex1);
vertex2 = node2;
AddVertice(vertex2);
vertex3 = node3;
AddVertice(vertex3);
CalcTriangle();
}
public Triangle(Point2d node1, Point2d node2, Point2d node3)
{
vertex1 = node1.ToPoint3d();
AddVertice(vertex1);
vertex2 = node2.ToPoint3d();
AddVertice(vertex2);
vertex3 = node3.ToPoint3d();
AddVertice(vertex3);
CalcTriangle();
}
public void CalcTriangle()
{
//Edge1 = new Line3d(vertex1, vertex2);
//Edge2 = new Line3d(vertex2, vertex3);
//Edge3 = new Line3d(vertex3, vertex1);
//Centroid = new Point3d((vertex1.X + vertex2.X + vertex3.X) / 3, (vertex1.Y + vertex2.Y + vertex3.Y) / 3, (vertex1.Z + vertex2.Z + vertex3.Z) / 3);
//Point3d minPt, maxPt;
//minPt = new Point3d(
// Math.Min(Math.Min(vertex1.X, vertex2.X), vertex3.X),
// Math.Min(Math.Min(vertex1.Y, vertex2.Y), vertex3.Y),
// Math.Min(Math.Min(vertex1.Z, vertex2.Z), vertex3.Z));
//maxPt = new Point3d(
// Math.Max(Math.Max(vertex1.X, vertex2.X), vertex3.X),
// Math.Max(Math.Max(vertex1.Y, vertex2.Y), vertex3.Y),
// Math.Max(Math.Max(vertex1.Z, vertex2.Z), vertex3.Z));
//BoundingBox = new BoundingBox2d(minPt.ToPoint2d(), maxPt.ToPoint2d());
double ang1, ang2, ang3;
ang1 = vertex1.AngleTo(vertex3, vertex2);
ang2 = vertex2.AngleTo(vertex1, vertex3);
ang3 = vertex3.AngleTo(vertex2, vertex1);
MaxAngleDeg = Math.Max(Math.Max(ang1, ang2), ang3);
CalcPolygon();
}
}
}

11
Geometry/UnitsEnums.cs Normal file
View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public enum UnitsLin { м = 1, см = 2, мм = 3, _ = 0 }
public enum UnitsArea { м = 1, см = 2, мм = 3, _ = 0 }
public enum UnitsForce { т = 1, кН = 3, Н = 4, кг = 2, _ = 0 }
public enum UnitsStress { т = 1, кН = 2, Н = 3, МПа = 4, кПа = 5, _ = 0 }
public enum UnitsList { _, м, см, мм, т, кг, Н, кН, кПа, МПа, градус, rad }

57
Geometry/Vector.cs Normal file
View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Geo
{
[Serializable]
public class Vector : IVector
{
double[] arr;
int n;
public int N { get => n; }
public double this[int i] { get => arr[i]; set => arr[i] = value; }
public Vector(int N)
{
n = N;
arr = new double[N];
}
public Vector(Vector source)
{
n = source.N;
arr = new double[source.N];
arr = (double[])source.arr.Clone();
}
public Vector(Vector3d source)
{
n = 3;
arr = new double[n];
arr[0] = source.Vx;
arr[1] = source.Vy;
arr[2] = source.Vz;
}
public Vector(double[] source)
{
n = source.Length;
arr = new double[source.Length];
arr = (double[])source.Clone();
}
public double[] ToArray()
{
return arr;
}
public Vector3d ToVector3d()
{
return new Vector3d { Vx = arr[0], Vy = arr[1], Vz = arr[2] };
}
}
}

97
Geometry/Vector2d.cs Normal file
View File

@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Math;
namespace Geo
{
[Serializable]
public class Vector2d
{
double[] arr = new double[2];
public double this[int i] { get => arr[i]; set => arr[i] = value; }
public double Vx { get => arr[0]; set => arr[0] = value; }
public double Vy { get => arr[1]; set => arr[1] = value; }
public double Norma { get => Sqrt(Pow(Vx, 2) + Pow(Vy, 2)); }
public double[] Unit { get => new double[] { Vx / Norma, Vy / Norma }; }
public Vector2d()
{
arr = new double[3];
}
public Vector2d(double v1, double v2)
{
arr = new double[2];
arr[0] = v1; arr[1] = v2;
}
public Vector2d(Vector2d source)
{
arr = new double[3];
arr = (double[])source.arr.Clone();
}
public Vector2d(Point2d source)
{
arr = new double[2];
arr[0] = source.X; arr[1] = source.Y;
}
public Vector2d(Vector source)
{
arr = new double[2];
if (source.N >= 2)
{
arr[0] = source[0]; arr[1] = source[1];
}
}
public Vector2d(double[] source)
{
arr = new double[2];
if (source.Length >= 2)
{
arr[0] = source[0]; arr[1] = source[1];
}
}
public static double CosAngleBetVectors(Vector2d v1, Vector2d v2)
{
return (v1.Vx * v2.Vx + v1.Vy * v2.Vy) / (Sqrt(v1.Vx * v1.Vx + v1.Vy * v1.Vy) * Sqrt(v2.Vx * v2.Vx + v2.Vy * v2.Vy));
}
public double[] ToArray()
{
return arr;
}
public Vector ToVector()
{
return new Vector(arr);
}
public static Vector3d operator ^(Vector2d v1, Vector2d v2)
{
Vector3d tempV1 = new Vector3d(v1); Vector3d tempV2 = new Vector3d(v2);
return new Vector3d
{
Vx = tempV1.Vy * tempV2.Vz - tempV1.Vz * tempV2.Vy,
Vy = tempV1.Vz * tempV2.Vx - tempV1.Vx * tempV2.Vz,
Vz = tempV1.Vx * tempV2.Vy - tempV1.Vy * tempV2.Vx
};
}
public static Vector2d operator *(Vector2d v1, Vector2d v2)
{
return new Vector2d
{
Vx = v1.Vx * v2.Vx,
Vy = v1.Vy * v2.Vy
};
}
}
}

107
Geometry/Vector3d.cs Normal file
View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Math;
namespace Geo
{
[Serializable]
public class Vector3d : IVector
{
double[] arr;
int n = 3;
public double this[int i] { get => arr[i]; set => arr[i] = value; }
public double Vx { get => arr[0]; set => arr[0] = value; }
public double Vy { get => arr[1]; set => arr[1] = value; }
public double Vz { get => arr[2]; set => arr[2] = value; }
public double Norma { get => Sqrt(Pow(Vx, 2) + Pow(Vy, 2) + Pow(Vz, 2)); }
public double[] Unit { get => new double[] { Vx / Norma, Vy / Norma, Vz / Norma }; }
public int N { get => n; }
public Vector3d()
{
arr = new double[3];
}
public Vector3d(Vector3d source)
{
arr = new double[3];
arr = (double[])source.arr.Clone();
}
public Vector3d(Point3d source)
{
arr = new double[3];
arr[0] = source.X; arr[1] = source.Y; arr[2] = source.Z;
}
public Vector3d(Vector source)
{
arr = new double[3];
if (source.N >= 3)
{
arr[0] = source[0]; arr[1] = source[1]; arr[2] = source[2];
}
}
public Vector3d(Vector2d source)
{
arr = new double[3];
arr[0] = source.Vx;
arr[1] = source.Vy;
arr[2] = 0;
}
public Vector3d(double[] source)
{
arr = new double[3];
if (source.Length >= 3)
{
arr[0] = source[0]; arr[1] = source[1]; arr[2] = source[2];
}
}
public static double CosAngleBetVectors(Vector3d v1, Vector3d v2)
{
return (v1.Vx * v2.Vx + v1.Vy * v2.Vy + v1.Vz * v2.Vz) / (Sqrt(v1.Vx* v1.Vx + v1.Vy* v1.Vy+ v1.Vz * v1.Vz) * Sqrt(v2.Vx * v2.Vx + v2.Vy * v2.Vy + v2.Vz * v2.Vz));
}
public double[] ToArray()
{
return arr;
}
public Vector2d ToVector2d()
{
return new Vector2d() { Vx = Vx, Vy = Vy };
}
public Vector ToVector()
{
return new Vector(arr);
}
public static Vector3d operator ^(Vector3d v1, Vector3d v2)
{
return new Vector3d
{
Vx = v1.Vy * v2.Vz - v1.Vz * v2.Vy,
Vy = v1.Vz * v2.Vx - v1.Vx * v2.Vz,
Vz = v1.Vx * v2.Vy - v1.Vy * v2.Vx
};
}
public static Vector3d operator *(Vector3d v1, Vector3d v2)
{
return new Vector3d
{
Vx = v1.Vx * v2.Vx,
Vy = v1.Vy * v2.Vy,
Vz = v1.Vz * v2.Vz
};
}
}
}