static class BezierSurface private const int размерность массива priva

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
static class BezierSurface
{
private const int n = 3;// размерность массива
private const int m = 4;// mBezierSurface (3 на 4)
private static Point3D[,] mBezierSurface = new Point3D[n, m]{//Второго порядка
// можно сделать 9, ставь m = 3 и подбирай координаты.
{ new Point3D(0, 0, 0), new Point3D(0, 0, 0.5), new Point3D(0, 0.5, 0), new Point3D(0, 0.5, 0.5) },
{ new Point3D(1, 0, 0), new Point3D(1, 0, 1), new Point3D(1, 1, 0), new Point3D(1, 1, 1) },
{ new Point3D(1, 0, 0), new Point3D(1, 0, 1), new Point3D(1, 1, 0), new Point3D(1, 2, 3) },
};
public class BSplineSurface
{
private double size;
private const int m = 4;// ненужный аппендикс, в топку его
private Point3D start = new Point3D(400, 220, 0);
private double psi;// огорчаешь: углы обзора
private double phi;// на поверхность
public BSplineSurface(double size, double psi, double phi)//конструктор класса
{
this.size = size;
this.psi = psi;
this.phi = phi;
}
Point3D[][] mBSplineSurface = new Point3D[][] {
new Point3D[] { new Point3D(0, 0, 0), new Point3D(0, 0, 0.5), new Point3D(0, 0.5, 0), new Point3D(0, 0.5, 0.5) },
new Point3D[] { new Point3D(0.5, 0, 0), new Point3D(0.5, 0, 0.5), new Point3D(0.5, 0.5, 0), new Point3D(0.5, 0.5, 0.5) },
new Point3D[] { new Point3D(2, 0, 0), new Point3D(2, 0, 2), new Point3D(2, 2, 0), new Point3D(2, 2, 2) }
};
private PointF Project(Point3D p)// метод проецирования трехмерной точки на двумерную плоскость
{
Point3D a1 = new Point3D(Math.Cos(phi), Math.Sin(phi), 0);
Point3D a2 = new Point3D(-1 * Math.Sin(phi) * Math.Sin(psi), Math.Cos(phi) * Math.Sin(psi), Math.Cos(psi));
double x = p.X - start.X;//?
double y = p.Y - start.Y;
double z = p.Z - start.Z;
return new PointF((float)(a1.scalyar(new Point3D(x, y, z)) * size), (float)(a2.scalyar(new Point3D(x, y, z)) * size));
}
public void Show(Graphics g, Pen pen)
{
List<Point3D> polygon = new List<Point3D>();// Лист для точек на сетке
for (double u = 0; u <= 1.0; u += 0.01)
{
for (double v = 0; v <= 1.0; v += 0.01)
{
var pList = new List<Point3D>();// Лист, в котором лежат точки сплайна.
for (int i = 0; i < mBSplineSurface.Length; i++)
{
for (int j = 0; j < mBSplineSurface.Length - 2; j++)
{
pList.Add(new Point3D((float)(0.5f * (1f - v) * (1f - v) * mBSplineSurface[i][j].X + (0.75f - (v - 0.5f) * (v - 0.5f)) * mBSplineSurface[i][j + 1].X + 0.5f * v * v * mBSplineSurface[i][j + 2].X),
(float)(0.5f * (1f - v) * (1f - v) * mBSplineSurface[i][j].Y + (0.75f - (v - 0.5f) * (v - 0.5f)) * mBSplineSurface[i][j + 1].Y + 0.5f * v * v * mBSplineSurface[i][j + 2].Y),
(float)(0.5f * (1f - v) * (1f - v) * mBSplineSurface[i][j].Z + (0.75f - (v - 0.5f) * (v - 0.5f)) * mBSplineSurface[i][j + 1].Z + 0.5f * v * v * mBSplineSurface[i][j + 2].Z)));
}
}
for (int j = 0; j < pList.Count - 2; j++)
{
polygon.Add(new Point3D((float)(0.5f * (1f - u) * (1f - u) * pList[j].X + (0.75f - (u - 0.5f) * (u - 0.5f)) * pList[j + 1].X + 0.5f * u * u * pList[j + 2].X),
(float)(0.5f * (1f - u) * (1f - u) * pList[j].Y + (0.75f - (u - 0.5f) * (u - 0.5f)) * pList[j + 1].Y + 0.5f * u * u * pList[j + 2].Y),
(float)(0.5f * (1f - u) * (1f - u) * pList[j].Z + (0.75f - (u - 0.5f) * (u - 0.5f)) * pList[j + 1].Z + 0.5f * u * u * pList[j + 2].Z)));
polygon.Last().X = (float)(polygon.Last().X + start.X);
polygon.Last().Y = (float)(polygon.Last().Y + start.Y);
polygon.Last().Z = (float)(polygon.Last().Z + start.Z);
}
}
var sub = polygon.Select(x => Project(x)).ToList();// создаем новый лист, в него кладем двухмерные точки.
// .Select(x => Project(x)) эта штука берет каждую точку из листа polygon и прогоняет в методе Project
for (int i = 0; i < sub.Count - 1; i++)
{
if (g.ClipBounds.Contains(sub[i]) && g.ClipBounds.Contains(sub[i + 1]))
{
g.DrawLine(pen, sub[i], sub[i + 1]);
}
}
polygon.Clear();
}
for (double v = 0; v <= 1.0; v += 0.01)
{
for (double u = 0; u <= 1.0; u += 0.01)
{
var pList = new List<Point3D>();
for (int i = 0; i < mBSplineSurface.Length; i++)
{
for (int j = 0; j < mBSplineSurface.Length - 2; j++)
{
pList.Add(new Point3D((float)(0.5f * (1f - v) * (1f - v) * mBSplineSurface[i][j].X + (0.75f - (v - 0.5f) * (v - 0.5f)) * mBSplineSurface[i][j + 1].X + 0.5f * v * v * mBSplineSurface[i][j + 2].X),
(float)(0.5f * (1f - v) * (1f - v) * mBSplineSurface[i][j].Y + (0.75f - (v - 0.5f) * (v - 0.5f)) * mBSplineSurface[i][j + 1].Y + 0.5f * v * v * mBSplineSurface[i][j + 2].Y),
(float)(0.5f * (1f - v) * (1f - v) * mBSplineSurface[i][j].Z + (0.75f - (v - 0.5f) * (v - 0.5f)) * mBSplineSurface[i][j + 1].Z + 0.5f * v * v * mBSplineSurface[i][j + 2].Z)));
}
}
for (int j = 0; j < pList.Count - 2; j++)
{
polygon.Add(new Point3D((float)(0.5f * (1f - u) * (1f - u) * pList[j].X + (0.75f - (u - 0.5f) * (u - 0.5f)) * pList[j + 1].X + 0.5f * u * u * pList[j + 2].X),
(float)(0.5f * (1f - u) * (1f - u) * pList[j].Y + (0.75f - (u - 0.5f) * (u - 0.5f)) * pList[j + 1].Y + 0.5f * u * u * pList[j + 2].Y),
(float)(0.5f * (1f - u) * (1f - u) * pList[j].Z + (0.75f - (u - 0.5f) * (u - 0.5f)) * pList[j + 1].Z + 0.5f * u * u * pList[j + 2].Z)));
polygon.Last().X = (float)(polygon.Last().X + start.X);
polygon.Last().Y = (float)(polygon.Last().Y + start.Y);
polygon.Last().Z = (float)(polygon.Last().Z + start.Z);
}
}
var sub = polygon.Select(x => Project(x)).ToList();// то же самое, что было выше
for (int i = 0; i < sub.Count - 1; i++)
{
if (g.ClipBounds.Contains(sub[i]) && g.ClipBounds.Contains(sub[i + 1]))
{
g.DrawLine(pen, sub[i], sub[i + 1]);
}
}
polygon.Clear();
}
}
}
}
class DrawSurface
{
private Graphics e;
private double a, b, c, d, phi, psi, Sx, Sy;// a,b,c,d - прямоугольник, ограничивающий поверхность. phi/psi - угол обзора, Sx, Sy - масштаб
private int Picture_CODE, BEGINX, BEGINY;//Picture_CODE - номер поверхность для отрисовки, BEGINX, BEGINY - точка, с которой будем рисовать
public DrawSurface(Graphics e, double a1, double b1, double c1, double d1, double phi, double psi, double Sx, double Sy, int Picture_CODE, int BEGINX, int BEGINY)
{
this.e = e;
a = a1;
b = b1;
c = c1;
d = d1;
this.phi = phi;
this.psi = psi;
this.Picture_CODE = Picture_CODE;
this.Sx = Sx;
this.Sy = Sy;
this.BEGINX = BEGINX;
this.BEGINY = BEGINY;
}
public void Draw()
{
List<Point3D> list = new List<Point3D>();
Point3D p = new Point3D();
Point3D a1 = new Point3D(Math.Cos(phi), Math.Sin(phi), 0);
Point3D a2 = new Point3D(-1 * Math.Sin(phi) * Math.Sin(psi), Math.Cos(phi) * Math.Sin(psi), Math.Cos(psi));
double u, v, du, dv, Nu = 20, Nv = 20;//u, v - точки на сетке, du,dv - шаг, Nu, Nv - разбиение
du = Math.Abs((b - a) / Nu);
dv = Math.Abs((d - c) / Nv);
Point temp = new Point(0, 0);
Point3D beg = new Point3D(0, 0, 0), cur = new Point3D(0, 0, 0);// точки на сетке
int u0, v0, v1, u1;// спроецированные точки
for (u = a; u <= b; u += du) // рисование по горизонтали
{
v = c;
beg = Function(u, v, Picture_CODE);
u0 = ((int)(Sx * scalyar(beg, a1)));
v0 = ((int)(Sy * scalyar(beg, a2)));
temp.X = BEGINX + u0;
temp.Y = BEGINY + v0;
for (v = c + dv; v <= d; v += dv)// рисование по горизонтали
{
cur = Function(u, v, Picture_CODE);
u1 = ((int)(Sx * scalyar(cur, a1)));
v1 = ((int)(Sy * scalyar(cur, a2)));
e.DrawLine(new Pen(Color.Black), BEGINX + u1, BEGINY + v1, temp.X, temp.Y);
temp.X = BEGINX + u1;
temp.Y = BEGINY + v1;
}
}
for (v = c; v <= d; v += dv)//// рисование по вертикали
{
u = a;
beg = Function(u, v, Picture_CODE);
u0 = ((int)(Sx * scalyar(beg, a1)));
v0 = ((int)(Sy * scalyar(beg, a2)));
temp.X = BEGINX + u0;
temp.Y = BEGINY + v0;
for (u = a + du; u <= b; u += du)
{
cur = Function(u, v, Picture_CODE);
u1 = ((int)(Sx * scalyar(cur, a1)));
v1 = ((int)(Sy * scalyar(cur, a2)));
e.DrawLine(new Pen(Color.Black), BEGINX + u1, BEGINY + v1, temp.X, temp.Y);
temp.X = BEGINX + u1;
temp.Y = BEGINY + v1;
}
}
}
private double scalyar(Point3D a, Point3D b)
{
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
}
public Point3D Function(double u, double v, int code)//Функция, которая возвращает значение для построения поверхности
{ // u, v положение на сетке(точка), code - номер фигуры, которую хочешь вывести. Дашь 0 - будешь поверхность Безье
switch (code)
{
case 0:
return BezierSurface.drawBezierSurface(u, v);
case 1:
return new Point3D(5 * Math.Cos(u) * Math.Atan(v), 5 * Math.Sin(u) * Math.Tanh(v), 5 * Math.Tanh(u * v));
case 2:
return new Point3D((5 + Math.Cos(u)) * Math.Cos(v), (5 + Math.Cos(u)) * Math.Sin(v), 5 * Math.Sin(u));
default:
return new Point3D(0, 0, 0);
}
}
}
}