00001 using System;
00002 using System.Collections.Generic;
00003 using System.Linq;
00004 using System.Text;
00005 using System.Windows;
00006 using System.Windows.Shapes;
00007 using System.Windows.Media;
00008 using System.Windows.Media.Imaging;
00009
00010 namespace EdgeClustering
00011 {
00012
00013
00014
00015
00016
00017 static class CardinalSpline
00018 {
00019
00020
00021
00022
00023
00024
00025 public static StreamGeometry CalculateCardinalSplinePath(Point[] points, double tension)
00026 {
00027 Point[] p = CalculateControlPoints(points, tension);
00028
00029 StreamGeometry geometry = new StreamGeometry();
00030
00031 using (StreamGeometryContext sgc = geometry.Open())
00032 {
00033 sgc.BeginFigure(p[0], true, false);
00034 for (int i = 1; i < p.Length; i +=3)
00035 {
00036 sgc.BezierTo(p[i], p[i + 1], p[i + 2], true, false);
00037 }
00038 }
00039
00040 return geometry;
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050 private static Point[] CalculateControlPoints(Point[] points, double tension)
00051 {
00052 Point[] p;
00053 int num = points.Length * 3 - 2;
00054 Point[] ctrlPoints = new Point[num];
00055 double t = tension * 1.0 / 3.0;
00056
00057
00058 ctrlPoints[0] = points[0];
00059 ctrlPoints[1] = CalculateEnd(points[0], points[1], t);
00060
00061 for (int i = 0; i < points.Length - 2; i++)
00062 {
00063 p = CaclculateCurve(new Point[]{points[i], points[i + 1], points[i + 2]}, t);
00064 ctrlPoints[3 * i + 2] = p[0];
00065 ctrlPoints[3 * i + 3] = points[i+1];
00066 ctrlPoints[3 * i + 4] = p[1];
00067 }
00068
00069
00070 ctrlPoints[num - 2] = CalculateEnd(points[points.Length - 1], points[points.Length - 2], t);
00071 ctrlPoints[num - 1] = points[points.Length - 1];
00072 return ctrlPoints;
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082 private static Point CalculateEnd(Point end, Point other, double tension)
00083 {
00084 return new Point(tension * (other.X - end.X) + end.X, tension * (other.Y - end.Y) + end.Y);
00085 }
00086
00087
00088
00089
00090
00091
00092
00093 private static Point[] CaclculateCurve(Point[] p, double tension)
00094 {
00095 double dx = p[2].X - p[0].X;
00096 double dy = p[2].Y - p[0].Y;
00097
00098 Point[] erg = new Point[2];
00099
00100 erg[0] = new Point(p[1].X - dx * tension, p[1].Y - dy * tension);
00101 erg[1] = new Point(p[1].X + dx * tension, p[1].Y + dy * tension);
00102
00103 return erg;
00104 }
00105 }
00106 }