Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Plot2DCurvePainter.cs
1using System;
2using SkiaSharp;
3
5{
10 {
20 public void DrawGraph(SKCanvas Canvas, SKPoint[] Points, object[] Parameters, SKPoint[] PrevPoints, object[] PrevParameters,
22 {
23 SKPaint Pen = null;
24 SKPath Path = null;
25
26 try
27 {
28 Pen = Graph.ToPen(Parameters[0], Parameters[1]);
29 Path = CreateSpline(Points);
30
31 Canvas.DrawPath(Path, Pen);
32 }
33 finally
34 {
35 Pen?.Dispose();
36 Path?.Dispose();
37 }
38 }
39
45 public static SKPath CreateSpline(params SKPoint[] Points)
46 {
47 return CreateSpline(null, Points);
48 }
49
56 public static SKPath CreateSpline(SKPath AppendTo, params SKPoint[] Points)
57 {
58 int i, c = Points.Length;
59 if (c == 0)
60 throw new ArgumentException("No points provided.", nameof(Points));
61
62 if (AppendTo is null)
63 {
64 AppendTo = new SKPath();
65 AppendTo.MoveTo(Points[0]);
66 }
67 else
68 AppendTo.LineTo(Points[0]);
69
70 if (c == 1)
71 return AppendTo;
72
73 if (c == 2)
74 {
75 AppendTo.LineTo(Points[1]);
76 return AppendTo;
77 }
78
79 double[] V = new double[c];
80
81 for (i = 0; i < c; i++)
82 V[i] = Points[i].X;
83
84 GetCubicBezierCoefficients(V, out double[] Ax, out double[] Bx);
85
86 for (i = 0; i < c; i++)
87 V[i] = Points[i].Y;
88
89 GetCubicBezierCoefficients(V, out double[] Ay, out double[] By);
90
91 for (i = 0; i < c - 1; i++)
92 {
93 AppendTo.CubicTo((float)Ax[i], (float)Ay[i], (float)Bx[i], (float)By[i],
94 Points[i + 1].X, Points[i + 1].Y);
95 }
96
97 return AppendTo;
98 }
99
106 public static void GetCubicBezierCoefficients(double[] V, out double[] A, out double[] B)
107 {
108 // Calculate Spline between points P[0], ..., P[N].
109 // Divide into segments, B[0], ...., B[N-1] of cubic Bezier curves:
110 //
111 // B[i](t) = (1-t)³P[i] + 3t(1-t)²A[i] + 3t²(1-t)B[i] + t³P[i+1]
112 //
113 // B'[i](t) = (-3+6t-3t²)P[i]+(3-12t+9t²)A[i]+(6t-9t²)B[i]+3t²P[i+1]
114 // B"[i](t) = (6-6t)P[i]+(-12+18t)A[i]+(6-18t)B[i]+6tP[i+1]
115 //
116 // Choose control points A[i] and B[i] such that:
117 //
118 // B'[i](1) = B'[i+1](0) => A[i+1]+B[i]=2P[i+1], i<N (eq 1)
119 // B"[i](1) = B"[i+1](0) => A[i]-2B[i]+2A[i+1]-B[i+1]=0 (eq 2)
120 //
121 // Also add the boundary conditions:
122 //
123 // B"[0](0)=0 => 2A[0]-B[0]=P[0] (eq 3)
124 // B"[N-1](1)=0 => -A[N-1]+2B[N-1]=P[N] (eq 4)
125 //
126 // Method solves this linear equation for one coordinate of A[i] and B[i] at a time.
127 //
128 // First, the linear equation, is reduced downwards. Only coefficients close to
129 // the diagonal, and in the right-most column need to be processed. Furthermore,
130 // we don't have to store values we know are zero or one. Since number of operations
131 // depend linearly on number of vertices, algorithm is O(N).
132
133 int N = V.Length - 1;
134 int N2 = N << 1;
135 int i = 0;
136 int j = 0;
137 double r11, r12, r15; // r13 & r14 always 0.
138 double r22, r23, r25; // r21 & r24 always 0 for all except last equation, where r21 is -1.
139 double /*r31,*/ r32, r33, r34, r35;
140 double[,] Rows = new double[N2, 3];
141 double a;
142
143 A = new double[N];
144 B = new double[N];
145
146 r11 = 2; // eq 3
147 r12 = -1;
148 r15 = V[j++];
149
150 r22 = 1; // eq 1
151 r23 = 1;
152 r25 = 2 * V[j++];
153
154 // r31 = 1; // eq 2
155 r32 = -2;
156 r33 = 2;
157 r34 = -1;
158 r35 = 0;
159
160 while (true)
161 {
162 a = 1 / r11;
163 // r11 = 1;
164 r12 *= a;
165 r15 *= a;
166
167 // r21 is always 0. No need to eliminate column.
168 // r22 is always 1. No need to scale row.
169
170 // r31 is always 1 at this point.
171 // r31 -= r11;
172 r32 -= r12;
173 r35 -= r15;
174
175 if (r32 != 0)
176 {
177 r33 -= r32 * r23;
178 r35 -= r32 * r25;
179 // r32 = 0;
180 }
181
182 // r33 is always 0.
183
184 // r11 always 1.
185 Rows[i, 0] = r12;
186 Rows[i, 1] = 0;
187 Rows[i, 2] = r15;
188 i++;
189
190 // r21, r24 always 0.
191 Rows[i, 0] = r22;
192 Rows[i, 1] = r23;
193 Rows[i, 2] = r25;
194 i++;
195
196 if (i >= N2 - 2)
197 break;
198
199 r11 = r33;
200 r12 = r34;
201 r15 = r35;
202
203 r22 = 1; // eq 1
204 r23 = 1;
205 r25 = 2 * V[j++];
206
207 // r31 = 1; // eq 2
208 r32 = -2;
209 r33 = 2;
210 r34 = -1;
211 r35 = 0;
212 }
213
214 r11 = r33;
215 r12 = r34;
216 r15 = r35;
217
218 //r21 = -1; // eq 4
219 r22 = 2;
220 r23 = 0;
221 r25 = V[j++];
222
223 a = 1 / r11;
224 //r11 = 1;
225 r12 *= a;
226 r15 *= a;
227
228 //r21 += r11;
229 r22 += r12;
230 r25 += r15;
231
232 r25 /= r22;
233 r22 = 1;
234
235 // r11 always 1.
236 Rows[i, 0] = r12;
237 Rows[i, 1] = 0;
238 Rows[i, 2] = r15;
239 i++;
240
241 // r21 and r24 always 0.
242 Rows[i, 0] = r22;
243 Rows[i, 1] = r23;
244 Rows[i, 2] = r25;
245 i++;
246
247 // Then eliminate back up:
248
249 j--;
250 while (i > 0)
251 {
252 i--;
253 if (i < N2 - 1)
254 {
255 a = Rows[i, 1];
256 if (a != 0)
257 {
258 Rows[i, 1] = 0;
259 Rows[i, 2] -= a * Rows[i + 1, 2];
260 }
261 }
262
263 B[--j] = Rows[i, 2];
264
265 i--;
266 a = Rows[i, 0];
267 if (a != 0)
268 {
269 Rows[i, 0] = 0;
270 Rows[i, 2] -= a * Rows[i + 1, 2];
271 }
272
273 A[j] = Rows[i, 2];
274 }
275 }
276 }
277}
Contains information about the current drawing area.
Definition: DrawingArea.cs:12
static SKPath CreateSpline(params SKPoint[] Points)
Creates a Spline path through a given set of points.
static SKPath CreateSpline(SKPath AppendTo, params SKPoint[] Points)
Creates a Spline path through a given set of points.
static void GetCubicBezierCoefficients(double[] V, out double[] A, out double[] B)
Gets a set of coefficients for cubic Bezier curves, forming a spline, one coordinate at a time.
void DrawGraph(SKCanvas Canvas, SKPoint[] Points, object[] Parameters, SKPoint[] PrevPoints, object[] PrevParameters, DrawingArea DrawingArea)
Draws the graph on a canvas.
Base class for graphs.
Definition: Graph.cs:79
static SKPaint ToPen(object Object, object Size)
Converts an object to a pen value.
Definition: Graph.cs:769
Interface for 2D graph drawing functions.
Definition: IPainter2D.cs:10