00001 using System;
00002 using System.Collections.Generic;
00003 using System.Linq;
00004 using System.Text;
00005 using System.Collections;
00006 using System.Windows.Media;
00007 using System.Windows;
00008
00009 namespace EdgeClustering
00010 {
00011
00012
00013
00014
00015
00016
00017 class Graph
00018 {
00019
00020
00021
00022
00023 public struct Settings{
00024 private static int gridSize = 5;
00025 public static int GridSize
00026 {
00027 get { return Settings.gridSize; }
00028 set { Settings.gridSize = value; }
00029 }
00030
00031 private static double kdeRadius = 30;
00032 public static double KdeRadius
00033 {
00034 get { return Settings.kdeRadius; }
00035 set { Settings.kdeRadius = value; }
00036 }
00037
00038 private static int kdeHistogramSize = 360;
00039 public static int KdeHistogramSize
00040 {
00041 get { return Settings.kdeHistogramSize; }
00042 set { Settings.kdeHistogramSize = value; }
00043 }
00044
00045 private static double kdeThreshold = 0.01;
00046 public static double KdeThreshold
00047 {
00048 get { return Settings.kdeThreshold; }
00049 set { Settings.kdeThreshold = value; }
00050 }
00051
00052 private static double border = 0.01;
00053
00054 public static double Border
00055 {
00056 get { return Settings.border; }
00057 set { Settings.border = value; }
00058 }
00059 }
00060
00061 private static double randomWidth = 100;
00062 private static double randomHeight = 100;
00063
00064 private int stage = 0;
00065 public int ComputingStage
00066 {
00067 get { return stage; }
00068 }
00069
00070 #region DataStructures
00071 private List<SimpleEdge> simpleEdges;
00072 public List<SimpleEdge> SimpleEdges
00073 {
00074 get { return simpleEdges; }
00075 }
00076
00077 private PointCollection points;
00078 public PointCollection Points
00079 {
00080 get { return points; }
00081 }
00082
00083 private ArrayList[,] grid;
00084 public ArrayList[,] Grid
00085 {
00086 get { return grid; }
00087 }
00088
00089 private double[,] kernelPeaks;
00090 public double[,] KernelPeaks
00091 {
00092 get { return kernelPeaks; }
00093 }
00094
00095 private List<MergedSegment> mergedSegments;
00096 public List<MergedSegment> MergedSegments
00097 {
00098 get { return mergedSegments; }
00099 }
00100
00101 private List<SimpleEdge> meshEdges;
00102 public List<SimpleEdge> MeshEdges
00103 {
00104 get { return meshEdges; }
00105 }
00106
00107 private ControlMesh controlMesh = new ControlMesh();
00108
00109 private List<EnhancedEdge> enhancedEdges;
00110 public List<EnhancedEdge> EnhancedEdges
00111 {
00112 get { return enhancedEdges; }
00113 }
00114 #endregion
00115
00116 public static double gridScale;
00117
00118 private double maxPointValue;
00119 public double MaxPointValue
00120 {
00121 get { return maxPointValue; }
00122 }
00123
00124 public ControlMesh ControlMesh { get { return controlMesh; } }
00125
00126
00127
00128
00129
00130
00131 public Graph(int points, int edges)
00132 {
00133 RandomInit(points, edges);
00134
00135 CalcGridScale();
00136 }
00137
00138
00139
00140
00141
00142 public Graph(string filename)
00143 {
00144 ReadXMLInit(filename);
00145 CalcGridScale();
00146 }
00147
00148
00149
00150
00151
00152 public void WriteXMLGraph(String filename)
00153 {
00154 XMLData.WriteLinkedNodes(simpleEdges,filename);
00155 }
00156
00157
00158
00159
00160
00161 public void ReadXMLInit(String filename)
00162 {
00163 simpleEdges = XMLData.ReadLinkedNodes(filename);
00164 points = new PointCollection();
00165
00166 foreach (SimpleEdge s in simpleEdges)
00167 {
00168 if (!points.Contains(s.A))
00169 points.Add(s.A);
00170 if (!points.Contains(s.B))
00171 points.Add(s.B);
00172 }
00173 }
00174
00175
00176
00177
00178
00179 private void TestInit(int size)
00180 {
00181 points = new PointCollection(size);
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 points.Add(new Point(4.3, 4.15));
00196 points.Add(new Point(19.8, 4.15));
00197 points.Add(new Point(16.6, 3.35));
00198 points.Add(new Point(20.8, 3.35));
00199 points.Add(new Point(1.3, 5));
00200 points.Add(new Point(10.9, 5));
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 simpleEdges = new List<SimpleEdge>(size);
00227
00228 simpleEdges.Add(new SimpleEdge(points[0], points[1]));
00229 simpleEdges.Add(new SimpleEdge(points[2], points[3]));
00230 simpleEdges.Add(new SimpleEdge(points[4], points[5]));
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 }
00282
00283
00284
00285
00286
00287
00288 private void RandomInit(int numofPoints, int numofEdges)
00289 {
00290 points = new PointCollection(numofPoints);
00291 Random r = new Random();
00292
00293 for (int i = 0; i < numofPoints; i++)
00294 {
00295 double x = r.NextDouble()*randomWidth;
00296 double y = r.NextDouble()*randomHeight;
00297
00298 points.Add(new Point(x, y));
00299 }
00300
00301
00302
00303 simpleEdges = new List<SimpleEdge>(numofPoints * numofEdges);
00304
00305 int n;
00306 foreach (Point p in points)
00307 {
00308 for (int i = 0; i < numofEdges; i++)
00309 {
00310 do
00311 {
00312 n = r.Next(points.Count);
00313 } while (points[n] == p);
00314
00315 simpleEdges.Add(new SimpleEdge(p, points[n]));
00316 }
00317 }
00318 }
00319
00320
00321
00322
00323 private void CalcGridScale()
00324 {
00325 if (points == null)
00326 return;
00327
00328 double yMax=0, xMax = 0;
00329
00330
00331 foreach (Point p in points)
00332 {
00333 xMax = (p.X > xMax) ? p.X : xMax;
00334 yMax = (p.Y > yMax) ? p.Y : yMax;
00335 }
00336
00337 maxPointValue = Math.Max(xMax, yMax) * (1 + Settings.Border);
00338 gridScale = maxPointValue / Settings.GridSize;
00339 }
00340
00341
00342
00343
00344
00345 public void Compute()
00346 {
00347 stage = 0;
00348
00349 CalcGridScale();
00350 CalculateGridElements();
00351 stage++;
00352
00353 CalculateKDEPeaks();
00354 stage++;
00355
00356 MergeSegments();
00357 stage++;
00358
00359 ComputeMeshEdges();
00360 stage++;
00361
00362
00363 controlMesh.CalculateControlMesh(meshEdges);
00364 stage++;
00365
00366 enhancedEdges = controlMesh.Intersect(simpleEdges);
00367 stage++;
00368 }
00369
00370 public void MoveControlMeshVertex(Point position,Vector move)
00371 {
00372 position.X /= gridScale;
00373 position.Y /= gridScale;
00374
00375
00376 }
00377
00378
00379
00380
00381 public void CalculateGridElements()
00382 {
00383 grid = new ArrayList[Settings.GridSize, Settings.GridSize];
00384
00385 foreach (SimpleEdge edge in simpleEdges)
00386 {
00387 double deltaX = edge.B.X - edge.A.X;
00388 double deltaY = edge.B.Y - edge.A.Y;
00389
00390 double d = deltaY / deltaX;
00391
00392 FillGrid(d, edge.Alpha, edge.A.X / gridScale, edge.B.X / gridScale,
00393 edge.A.Y / gridScale, edge.B.Y / gridScale);
00394 }
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 public void FillGrid(double deltavalue, double angle, double Ax, double Bx, double Ay, double By)
00408 {
00409 if ((Ax == Bx && Ay == By) || deltavalue == double.NaN)
00410 return;
00411 int x = (int)Ax;
00412 double d = deltavalue;
00413 Console.WriteLine("(" + Ax + ", " + Ay + ") - (" + Bx + ", " + By + ")");
00414 int xmin = (int)(Math.Min(Ax, Bx)), xmax = (int)Math.Max(Ax, Bx), ymin = (int)(Math.Min(Ay, By)), ymax = (int)Math.Max(Ay, By);
00415
00416
00417 if (grid[x, (int)Ay] == null)
00418 grid[x, (int)Ay] = new ArrayList();
00419 grid[x, (int)Ay].Add(angle);
00420
00421 if (Ax < Bx)
00422 {
00423 x++;
00424 while (x < Bx)
00425 {
00426
00427 int ypos = (int)(Ay + ((double)x - Ax) * d);
00428
00429
00430 if (ypos < 0 || ypos >= grid.GetLength(1) || ypos > ymax || ypos < ymin)
00431 {
00432 x++;
00433 continue;
00434 }
00435
00436 if (grid[x, ypos] == null)
00437 grid[x, ypos] = new ArrayList();
00438 grid[x, ypos].Add(angle);
00439
00440 x++;
00441 }
00442 }
00443 else
00444 {
00445 while (x > Bx)
00446 {
00447
00448 int ypos = (int)(Ay + ((double)x - Ax) * d);
00449
00450
00451 if (ypos < 0 || ypos >= grid.GetLength(1) || ypos > ymax || ypos < ymin || x < 1)
00452 {
00453 x--;
00454 continue;
00455 }
00456
00457 if (grid[x - 1, ypos] == null)
00458 grid[x - 1, ypos] = new ArrayList();
00459 grid[x - 1, ypos].Add(angle);
00460
00461 x--;
00462 }
00463 }
00464
00465 int y = (int)Ay;
00466
00467 if (Ay < By)
00468 {
00469 y++;
00470 while (y < By)
00471 {
00472
00473 int xpos = (int)(((double)(y - Ay) / d) + Ax);
00474
00475
00476 if (xpos < 0 || xpos >= grid.GetLength(0) || xpos > xmax || xpos < xmin)
00477 {
00478 y++;
00479 continue;
00480 }
00481
00482 if (grid[xpos, y] == null)
00483 grid[xpos, y] = new ArrayList();
00484 grid[xpos, y].Add(angle);
00485
00486 y++;
00487 }
00488 }
00489 else
00490 {
00491 while (y > By)
00492 {
00493
00494 int xpos = (int)(((double)(y - Ay) / d) + Ax);
00495
00496
00497 if (xpos < 0 || xpos >= grid.GetLength(0) || xpos > xmax || xpos < xmin || y < 1)
00498 {
00499 y--;
00500 continue;
00501 }
00502
00503 if (grid[xpos, y - 1] == null)
00504 grid[xpos, y - 1] = new ArrayList();
00505 grid[xpos, y - 1].Add(angle);
00506
00507 y--;
00508 }
00509 }
00510 }
00511
00512
00513
00514
00515
00516 public void CalculateKDEPeaks()
00517 {
00518
00519 KernelDensityEstimator.HistogramSize = Settings.KdeHistogramSize;
00520 KernelDensityEstimator.GenerateKernel(Settings.KdeRadius);
00521
00522
00523 kernelPeaks = new double[Settings.GridSize, Settings.GridSize];
00524
00525
00526
00527 for (int x = 0; x < Settings.GridSize; x++)
00528 {
00529 for (int y = 0; y < Settings.GridSize; y++)
00530 {
00531 if (grid[x, y] != null)
00532 kernelPeaks[x, y] = KernelDensityEstimator.CalculateMaximum((double[])grid[x, y].ToArray(typeof(double)), Settings.KdeThreshold);
00533 else
00534 kernelPeaks[x, y] = -1;
00535 }
00536 }
00537 }
00538
00539
00540
00541
00542 public void MergeSegments()
00543 {
00544
00545 mergedSegments = new List<MergedSegment>();
00546
00547
00548 for (int x = 0; x < Settings.GridSize; x++)
00549 {
00550 for (int y = 0; y < Settings.GridSize; y++)
00551 {
00552 if (kernelPeaks[x, y] != -1)
00553 {
00554 MergedSegment s = new MergedSegment(new MergedSegment.Segment(x, y, kernelPeaks[x, y], grid[x, y].Count));
00555 int i = mergedSegments.IndexOf(s);
00556
00557 while (i != -1)
00558 {
00559 s.AddMergedSegment(mergedSegments[i]);
00560 mergedSegments.RemoveAt(i);
00561
00562 i = mergedSegments.IndexOf(s);
00563 }
00564
00565 mergedSegments.Add(s);
00566
00567 }
00568 }
00569 }
00570
00571 }
00572
00573
00574
00575
00576 private void ComputeMeshEdges()
00577 {
00578 meshEdges = new List<SimpleEdge>();
00579
00580 SimpleEdge tmp;
00581 foreach (MergedSegment ms in mergedSegments) if ((tmp = ms.CalculateMeshEdge()) != null) meshEdges.Add(tmp);
00582 }
00583 }
00584 }