// these sources don't seem to agree, and what I ended up using is still different. WHY? // http://en.wikipedia.org/wiki/Generalised_circle // http://www.math.ubc.ca/~cass/research/pdf/Geometry.pdf // http://www.math.okstate.edu/~wrightd/INDRA/MobiusonCircles.mpl public static CircLine operator *(Mobius m, CircLine circLine) { #if true Mobius inverse = m.Inverse; Mobius b = new Mobius(new Complex(circLine.a, 0), circLine.b.Conjugate, circLine.b, new Complex(circLine.c, 0)); Mobius hermitian = inverse.Transpose * new Mobius(new Complex(circLine.a, 0), circLine.b.Conjugate, circLine.b, new Complex(circLine.c, 0)) * inverse.Conjugate; return(CircLine.Create(hermitian.A.Re, hermitian.C, hermitian.D.Re)); #else // do it by decomposing the mobius -- slower Complex a = m.A; Complex b = m.B; Complex c = m.C; Complex d = m.D; CircLine toInvert, inverted, scaled; if (c == Complex.Zero) { scaled = circLine.Scale(a / d); return(scaled.Translate(b / d)); } toInvert = circLine.Translate(d / c); inverted = toInvert.Inverse; scaled = inverted.Scale(-(a * d - b * c) / (c * c)); return(scaled.Translate(a / c)); #endif }
public override List <Intersection> Intersect(CircLine other) { List <Intersection> intersections = new List <Intersection>(); if (other is Circle) { Circle otherC = (Circle)other; intersections = otherC.Intersect(this); if (intersections == null) { intersections = otherC.Intersect(this); } return(intersections.Select(i => new CircLine.Intersection(i.Point, i.ParamB, i.ParamA)).ToList()); } Line line = (Line)other; Complex denominator = b.Conjugate * line.b - b * line.b.Conjugate; if (denominator == Complex.Zero) { return(null); } Complex z = -(b * line.c - line.b * c) / denominator; intersections.Add(new Intersection(z, Project(z).Param, line.Project(z).Param)); return(intersections); }
public bool Equals(CircLine circLine) { if (circLine == null) { return(false); } return(Accuracy.LengthEquals(a, circLine.a) && b == circLine.b && Accuracy.LengthEquals(c, circLine.c)); }
public override bool IsNormalTo(CircLine circLine) { if (circLine is Line) { return(Math.Abs(Angle - ((Line)circLine).Angle) % (2 * Math.PI) == Math.PI); } Complex center = ((Circle)circLine).Center; return(this.Project(center).Point == center); }
public override bool IsNormalTo(CircLine circLine) { if (circLine is Line) { return(circLine.IsNormalTo(this)); } List <Intersection> intersections = this.Intersect(circLine); if (intersections == null || intersections.Count == 0) { return(false); } Circle other = (Circle)circLine; Complex p = intersections[0].Point; return(Accuracy.AngularTolerance > Math.Abs((p - this.Center).ModulusSquared + (p - other.Center).ModulusSquared - (this.Center - other.Center).ModulusSquared)); }
public TrimmedCircLine(CircLine circLine, Interval bounds) { this.circLine = circLine; this.bounds = bounds; }
public override bool IsNormalTo(CircLine circLine) { if (circLine is Line) return Math.Abs(Angle - ((Line)circLine).Angle) % (2 * Math.PI) == Math.PI; Complex center = ((Circle)circLine).Center; return this.Project(center).Point == center; }
public override List<Intersection> Intersect(CircLine other) { List<Intersection > intersections = new List<Intersection>(); if (other is Circle) { Circle otherC = (Circle)other; intersections = otherC.Intersect(this); if (intersections == null) intersections = otherC.Intersect(this); return intersections.Select(i => new CircLine.Intersection(i.Point, i.ParamB, i.ParamA)).ToList(); } Line line = (Line)other; Complex denominator = b.Conjugate * line.b - b * line.b.Conjugate; if (denominator == Complex.Zero) return null; Complex z = -(b * line.c - line.b * c) / denominator; intersections.Add(new Intersection(z, Project(z).Param, line.Project(z).Param)); return intersections; }
public override List <Intersection> Intersect(CircLine other) { List <Intersection> intersections = new List <Intersection>(); if (other is Circle) { Circle otherC = (Circle)other; Complex p0 = this.Center; Complex p1 = otherC.Center; double d = (p1 - p0).Modulus; double r0 = this.Radius; double r1 = otherC.Radius; if (d > (r0 + r1)) // outside { return(null); } if (d < Math.Abs(r0 - r1)) { return(intersections); } if (d == 0) { return(intersections); } double a = (r0 * r0 - r1 * r1 + d * d) / (2 * d); double h = Math.Sqrt(r0 * r0 - a * a); Complex p2 = p0 + a * (p1 - p0) / d; Complex intersect; intersect = new Complex( p2.Re + h * (p1.Im - p0.Im) / d, p2.Im - h * (p1.Re - p0.Re) / d ); intersections.Add(new Intersection( intersect, Math.Atan2(p0.Im - intersect.Im, p0.Re - intersect.Re), Math.Atan2(p1.Im - intersect.Im, p1.Re - intersect.Re) )); intersect = new Complex( p2.Re - h * (p1.Im - p0.Im) / d, p2.Im + h * (p1.Re - p0.Re) / d ); intersections.Add(new Intersection( intersect, Math.Atan2(p0.Im - intersect.Im, p0.Re - intersect.Re), Math.Atan2(p1.Im - intersect.Im, p1.Re - intersect.Re) )); return(intersections); } Line line = (Line)other; Complex nearPoint = line.Project(Center).Point - line.Origin; double dist = (Center - nearPoint).Modulus; if (dist - Radius > 0) { return(null); } Complex p; p = Line.Create(nearPoint, line.Angle).Evaluate(Math.Sqrt(RadiusSquared - dist * dist)); intersections.Add(new Intersection( p, line.Angle - Math.Asin(dist / Radius), line.Project(p).Param )); p = Line.Create(nearPoint, line.Angle).Evaluate(-Math.Sqrt(RadiusSquared - dist * dist)); intersections.Add(new Intersection( p, line.Angle + Math.Asin(dist / Radius) + Math.PI, line.Project(p).Param )); return(intersections); }
public abstract List<Intersection> Intersect(CircLine other);
public override bool IsNormalTo(CircLine circLine) { if (circLine is Line) return circLine.IsNormalTo(this); List<Intersection > intersections = this.Intersect(circLine); if (intersections == null || intersections.Count == 0) return false; Circle other = (Circle)circLine; Complex p = intersections[0].Point; return Accuracy.AngularTolerance > Math.Abs((p - this.Center).ModulusSquared + (p - other.Center).ModulusSquared - (this.Center - other.Center).ModulusSquared); }
public override List<Intersection> Intersect(CircLine other) { List<Intersection > intersections = new List<Intersection>(); if (other is Circle) { Circle otherC = (Circle)other; Complex p0 = this.Center; Complex p1 = otherC.Center; double d = (p1 - p0).Modulus; double r0 = this.Radius; double r1 = otherC.Radius; if (d > (r0 + r1)) // outside return null; if (d < Math.Abs(r0 - r1)) return intersections; if (d == 0) return intersections; double a = (r0 * r0 - r1 * r1 + d * d) / (2 * d); double h = Math.Sqrt(r0 * r0 - a * a); Complex p2 = p0 + a * (p1 - p0) / d; Complex intersect; intersect = new Complex( p2.Re + h * (p1.Im - p0.Im) / d, p2.Im - h * (p1.Re - p0.Re) / d ); intersections.Add(new Intersection( intersect, Math.Atan2(p0.Im - intersect.Im, p0.Re - intersect.Re), Math.Atan2(p1.Im - intersect.Im, p1.Re - intersect.Re) )); intersect = new Complex( p2.Re - h * (p1.Im - p0.Im) / d, p2.Im + h * (p1.Re - p0.Re) / d ); intersections.Add(new Intersection( intersect, Math.Atan2(p0.Im - intersect.Im, p0.Re - intersect.Re), Math.Atan2(p1.Im - intersect.Im, p1.Re - intersect.Re) )); return intersections; } Line line = (Line)other; Complex nearPoint = line.Project(Center).Point - line.Origin; double dist = (Center - nearPoint).Modulus; if (dist - Radius > 0) return null; Complex p; p = Line.Create(nearPoint, line.Angle).Evaluate(Math.Sqrt(RadiusSquared - dist * dist)); intersections.Add(new Intersection( p, line.Angle - Math.Asin(dist / Radius), line.Project(p).Param )); p = Line.Create(nearPoint, line.Angle).Evaluate(-Math.Sqrt(RadiusSquared - dist * dist)); intersections.Add(new Intersection( p, line.Angle + Math.Asin(dist / Radius) + Math.PI, line.Project(p).Param )); return intersections; }
public abstract List <Intersection> Intersect(CircLine other);
public abstract bool IsNormalTo(CircLine circLine);
public TrimmedCircLine(Complex start, Complex end) { this.circLine = Line.Create(start, end); this.bounds = circLine.MinorInterval(CircLine.Project(start).Param, CircLine.Project(end).Param); }
public bool Equals(CircLine circLine) { if (circLine == null) return false; return Accuracy.LengthEquals(a, circLine.a) && b == circLine.b && Accuracy.LengthEquals(c, circLine.c); }