using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace SoddyCrescent
{
public class SoddyCircle
{
public readonly double curvature;
public readonly double radius;
public SoddyCircle(double curvature)
{
this.curvature = curvature;
radius = Math.Abs(1 / curvature);
}
public override string ToString()
{
string s = String.Format("curvature: {0}\t\tradius: {1}", curvature, radius);
return s;
}
} // class SoddyCircle
public class ForthSoddyCircle
{
private List<SoddyCircle> forthSoddyCircle;
public ReadOnlyCollection<SoddyCircle> rdOnlyForthSoddyCircle
{
get { return forthSoddyCircle.AsReadOnly(); }
}
public ForthSoddyCircle(double curvature1, double curvature2, double curvature3)
{
forthSoddyCircle = new List<SoddyCircle>();
double K1K2_K2K3_K3K1_Prod = curvature1 * curvature2 + curvature2 * curvature3 + curvature3 * curvature1;
if ((K1K2_K2K3_K3K1_Prod < 0) &&
(Math.Abs(K1K2_K2K3_K3K1_Prod)<.0000000000001))
{
K1K2_K2K3_K3K1_Prod = 0.0;
}
if (K1K2_K2K3_K3K1_Prod < 0)
{
throw new System.ArgumentException("Impossible curvatures for Soddy circles.");
}
forthSoddyCircle.Add(new SoddyCircle(curvature1 + curvature2 + curvature3 + 2 * (Math.Sqrt(K1K2_K2K3_K3K1_Prod))));
if (K1K2_K2K3_K3K1_Prod == 0) return;
forthSoddyCircle.Add(new SoddyCircle(curvature1 + curvature2 + curvature3 - 2 * (Math.Sqrt(K1K2_K2K3_K3K1_Prod))));
}
} // class ForthSoddyCircle
}
using System;
using System.Windows;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace SoddyCrescent
{
public class CoOrd
{
/*
public override string ToString()
{
return (String.Format("({0},{1})", x, y));
}
*/
public static double DistanceSquared(Point p0, Point p1)
{
// return (Math.Pow(p0.x - p1.x, 2) + Math.Pow(p0.y - p1.y, 2));
return (p0.X - p1.X) * (p0.X - p1.X) + (p0.Y - p1.Y) * (p0.Y - p1.Y);
}
} // class CoOrd
public class MyCircle
{
public double radius;
public Point center;
// kappa = .5522847490
private static double Kappa = (Math.Sqrt(2) - 1) * 4 / 3;
public MyCircle()
{
radius = 0;
center = new Point();
}
public MyCircle(double radius, Point coord)
{
this.radius = radius;
center = coord;
}
public override string ToString()
{
string s = String.Format("radius: {0}\t\t", radius);
s += "center: " + center.ToString();
return s;
}
public Curve GenerateCurve()
{
Curve curve = new Curve(4); // 4 bezier segments in curve for circle
// start and endpoint for each segment
curve.startPoint = new Point(center.X, center.Y - radius); //down from center
curve.points[2] = new Point(center.X + radius, center.Y); //right from center
curve.points[5] = new Point(center.X, center.Y + radius); //up from center
curve.points[8] = new Point(center.X - radius, center.Y); //left from center
curve.points[11] = new Point(center.X, center.Y - radius); //down from center (same as start point)
double rk = radius * Kappa;
curve.points[0] = new Point(curve.startPoint.X + rk, curve.startPoint.Y);
curve.points[1] = new Point(curve.points[2].X, curve.points[2].Y - rk);
curve.points[3] = new Point(curve.points[2].X, curve.points[2].Y + rk);
curve.points[4] = new Point(curve.points[5].X + rk, curve.points[5].Y);
curve.points[6] = new Point(curve.points[5].X - rk, curve.points[5].Y);
curve.points[7] = new Point(curve.points[8].X, curve.points[8].Y + rk);
curve.points[9] = new Point(curve.points[8].X, curve.points[8].Y - rk);
curve.points[10] = new Point(curve.points[11].X-rk, curve.points[11].Y);
return curve;
}
} // class MyCircle
public class Intersect
{
private List<Point> intersects;
public ReadOnlyCollection<Point> rdOnlyIntersects
{
get { return intersects.AsReadOnly(); }
}
public Intersect()
{
intersects = new List<Point>();
}
public void AddIntersect(Point intersect)
{
intersects.Add(intersect);
}
} // class Intersect
public class CircleIntersect
// Given 2 circles P0 and P1
// p2 is the CoOrd of the point at the intersection of the line
// between the circle centers and the chord line between the intersections.
// the p1-->p2 distance is a
// the p0-->p2 distance is b
// h is the p2-->intersect distance on the chord
{
private MyCircle P0, P1;
private double dSquared; //distance squared between centers
private double d; //distance between centers
private double a, b;
private Point p2;
private double h;
private double dx, dy;
public Intersect intersects;
public CircleIntersect(MyCircle P0, MyCircle P1)
{
intersects = new Intersect();
p2 = new Point();
this.P0 = P0;
this.P1 = P1;
dSquared = CoOrd.DistanceSquared(P0.center, P1.center);
d = Math.Sqrt(dSquared);
if (d > P1.radius + P0.radius)
return;
if (d < Math.Abs(P1.radius - P0.radius))
return;
b = (P0.radius * P0.radius - P1.radius * P1.radius + dSquared) / (2 * d);
a = d - b;
double dx = P0.center.X - P1.center.X;
p2.X = P1.center.X + (a / d) * dx;
double dy = P0.center.Y - P1.center.Y;
p2.Y = P1.center.Y + (a / d) * dy;
h = Math.Sqrt(P1.radius * P1.radius - a * a);
dx = (P1.center.Y - P0.center.Y) * (h / d);
dy = (P1.center.X - P0.center.X) * (h / d);
intersects.AddIntersect(new Point((p2.X + dx), (p2.Y - dy)));
intersects.AddIntersect(new Point((p2.X - dx), (p2.Y + dy)));
}
private string CheckIntersect(Point i, MyCircle P)
{
Double sum;
sum = (i.X - P.center.X) * (i.X - P.center.X);
sum += (i.Y - P.center.Y) * (i.Y - P.center.Y);
sum -= P.radius * P.radius;
return ("Check sum: " + sum);
}
public void ShowIntersect()
{
Console.WriteLine("==== CircleIntersect ====");
Console.WriteLine("\tcircle P0: " + P0.ToString());
Console.WriteLine("\tcircle P1: " + P1.ToString());
Console.WriteLine("\tdSquared: " + dSquared);
Console.WriteLine("\td: " + d);
Console.WriteLine("\ta: " + a);
Console.WriteLine("\tb: " + b);
Console.WriteLine("p2: " + p2.ToString());
Console.WriteLine("h: " + h);
ReadOnlyCollection<Point> inter = intersects.rdOnlyIntersects;
for (int i = 0; i < inter.Count; i++)
{
Console.WriteLine("\tintersect: " + inter[i].ToString());
Console.WriteLine(CheckIntersect(inter[i], P0));
Console.WriteLine(CheckIntersect(inter[i], P1));
}
Console.WriteLine("\t\t\t====");
}
} // class CircleIntersect
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace SoddyCrescent
{
public class GrafCan
{
private double xScale;
public double XScale
{ get { return xScale; } }
private double yScale;
public double YScale
{ get { return yScale; } }
private double yMax;
public double YMAx
{ get { return yMax; } }
private double yMin;
public double YMin
{ get { return yMin; } }
private double actWidth;
public double ActWidth
{ get { return actWidth; } }
private double actHeight;
public double ActHeight
{ get { return actHeight; } }
private double yZero;
public Canvas can;
public GrafCan(double actWidth, double actHeight, double yMax, double yMin, Canvas can)
{
this.can = can;
this.actWidth = actWidth;
this.actHeight = actHeight;
this.yMax = yMax;
this.yMin = yMin;
yScale = actHeight / (yMax - yMin);
xScale = actWidth;
// xScale = actWidth / 2 * Math.PI;
yZero = yMax * yScale;
} // ctor
public Point GraphPoint(Point curvePoint)
{
Point grafPoint = new Point();
grafPoint.X = curvePoint.X * xScale;
grafPoint.Y = yZero - curvePoint.Y * yScale;
return grafPoint;
} // GraphPoint()
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace SoddyCrescent
{
public class CurveStyle
{
public double strokeThickness;
public Brush brush;
public Brush fillBrush;
public CurveStyle()
{
strokeThickness = 1;
brush = new SolidColorBrush(Colors.Black);
} //ctor
public CurveStyle(double strokeThickness, Brush brush)
{
this.strokeThickness = strokeThickness;
this.brush = brush;
} //ctor
} // class Style
public class Curve
{
public static List<Point> bPts = new List<Point>(); //for debugging!!!!!
public Point startPoint;
public Point[] points;
public Boolean hasBeenAdded; //to canvas children
public int addedAt; //canvas child number
public CurveStyle style;
public Curve(int numberPoints)
{
points = new Point[numberPoints * 3]; //each Bezier in a polybs has 3 points
style = new CurveStyle();
}
private Curve()
{
style = new CurveStyle();
}
public Curve Graf(GrafCan gc)
{
Curve grafCurve = new Curve();
grafCurve.style = style;
grafCurve.points = new Point[points.Length];
grafCurve.startPoint = gc.GraphPoint(startPoint);
for (int i = 0; i < points.Length; i++)
grafCurve.points[i] = gc.GraphPoint(points[i]);
return grafCurve;
} // Graf()
public PathGeometry ToGeometry(Curve c)
{
PolyBezierSegment pbs = new PolyBezierSegment(c.points, true);
//put single PolyBezierSegment into a PathSegmentCollection
PathSegmentCollection psc = new PathSegmentCollection();
psc.Add(pbs);
PathFigure pf = new PathFigure();
pf.StartPoint = c.startPoint;
pf.Segments = psc;
PathFigureCollection pfc = new PathFigureCollection();
pfc.Add(pf);
PathGeometry pg = new PathGeometry();
pg.Figures = pfc;
return pg;
}
public void ToString()
{
Console.WriteLine("Curve - " + points.Length + " DataFormat points");
Console.WriteLine("\tstartPoint: " + startPoint.ToString());
for (int i = 1; i <= points.Length; i++)
{
Console.WriteLine("\tP" + i + ": " + points[i - 1].ToString());
}
}
public static void ShowPoints(GrafCan gc, Point[] points)
{
Path path = new Path();
path.Stroke = Brushes.Green;
path.StrokeThickness = 1;
GeometryGroup gg = new GeometryGroup();
foreach (Point p in points)
{
Point gp = gc.GraphPoint(p);
EllipseGeometry eg = new EllipseGeometry(gp, 3, 3);
gg.Children.Add(eg);
}
path.Data = gg;
gc.can.Children.Add(path);
} // ShowPoints()
public void ShowControlPoints(GrafCan gc)
{
Curve cGraf = Graf(gc); //create new curve adjusted to geometry
Path path = new Path();
path.Stroke = Brushes.Green;
path.StrokeThickness = 1;
GeometryGroup gg = new GeometryGroup();
foreach (Point p in cGraf.points)
{
EllipseGeometry eg = new EllipseGeometry(p, 3, 3);
gg.Children.Add(eg);
}
path.Data = gg;
gc.can.Children.Add(path);
Path endPointPath = new Path();
endPointPath.Stroke = Brushes.Black;
endPointPath.StrokeThickness = 2;
GeometryGroup egg = new GeometryGroup();
EllipseGeometry egStart = new EllipseGeometry(cGraf.startPoint, 3, 3);
egg.Children.Add(egStart);
for (int i = 2; i < cGraf.points.Length; i += 3)
{
EllipseGeometry eg = new EllipseGeometry(cGraf.points[i], 3, 3);
egg.Children.Add(eg);
}
endPointPath.Data = egg;
gc.can.Children.Add(endPointPath);
} // ShowControlPoints()
public void AddCurveToCan(GrafCan gc)
{
Curve cGraf = Graf(gc); //create new curve adjusted to geometry
// cGraf.ToString();
// MyPath.Data = c.ToGeometry(cGraf);
Path p = new Path();
// p.Fill = new SolidColorBrush(Colors.LightCyan);
p.StrokeThickness = style.strokeThickness;
// p.Fill =
p.Stroke = style.brush;
p.Fill = style.fillBrush;
// p.Stretch = Stretch.Fill;
p.Data = ToGeometry(cGraf);
// gc.can.Children.Add(p);
if (!hasBeenAdded)
{
gc.can.Children.Add(p);
hasBeenAdded = true;
addedAt = gc.can.Children.Count - 1;
}
else
{
gc.can.Children.RemoveAt(addedAt);
gc.can.Children.Insert(addedAt, p);
}
} // AddCurveToCan()
public Curve CopyCurveAndMove(double dx, double dy)
{
Curve cc = new Curve(points.Length / 3);
cc.style.strokeThickness = style.strokeThickness;
cc.style.brush = style.brush;
cc.startPoint.X = startPoint.X + dx;
cc.startPoint.Y = startPoint.Y + dy;
int i = 0;
foreach (Point p in points)
{
cc.points[i].X = p.X + dx;
cc.points[i].Y = p.Y + dy;
i++;
}
return cc;
} // CopyCurveAndMove()
} // class Curve
}