public override bool HitTest(Ray3 ray, out double t) { ray = ray.Transform(InvPosition); double dx = ray.Direction.X; double dy = ray.Direction.Y; double dz = ray.Direction.Z; double x0 = ray.Position.X; double y0 = ray.Position.Y; double z0 = ray.Position.Z; double a = 1.0; //assume ray direction is normalized dx * dx + dy * dy + dz * dz; double b = 2.0 * (x0 * dx + y0 * dy + z0 * dz); double c = x0 * x0 + y0 * y0 + z0 * z0 - rad * rad; bool found = false; t = double.MaxValue; foreach (var tt in RealPolynomial.SolveQuadric(a, b, c)) { if (tt > 1e-4 && tt < t) { t = tt; found = true; } } return(found); }
public static double[] CircleLineParametric(Circle2d c, Line2d l) { double dx = l.X2 - l.X1; double dy = l.Y2 - l.Y1; double px = l.X1; double py = l.Y1; double cx = c.Center.X; double cy = c.Center.Y; double pa = dx * dx + dy * dy; double pb = 2.0 * (px * dx - cx * dx + py * dy - cy * dy); double pc = px * px - 2.0 * px * cx + cx * cx + py * py - 2.0 * py * cy + cy * cy - c.Radius * c.Radius; return(RealPolynomial.SolveQuadric(pa, pb, pc)); }
public static double[] ParabolaLineParamteric(Parabola2d pab, Line2d lin) //tested ok { double x1, y1, x2, y2; //line points in parabola standard position Transform2d tr = pab.ToStandardPosition; //intersect line with y=x^2 => easier tr.Apply(lin.X1, lin.Y1, out x1, out y1, true); tr.Apply(lin.X2, lin.Y2, out x2, out y2, true); double dx = x2 - x1; double dy = y2 - y1; double c2 = -dx * dx; double c1 = dy - 2 * dx * x1; double c0 = y1 - x1 * x1; //y1-x1^2+t*(dy-2*dx*x1)-dx^2*t^2=0 double[] ts = RealPolynomial.SolveQuadric(c2, c1, c0); return(ts); }
public Vector2d Normal(Point2d pt) { double x = pt.X - center.X; double y = pt.Y - center.Y; double a = MajorRadius; double b = MinorRadius; double e2 = x; double e1 = b * b - a * a - y * y - x * x; double e0 = x * a * a - x * b * b; double[] roots = RealPolynomial.SolveQuadric(e2, e1, e0); if (roots == null) { return(null); } Vector2d norm = new Vector2d(x - roots[0], y).Normalized; return(norm); }
public override bool HitTest(Ray3 ray, out double t) { ray = ray.Transform(InvPosition); double dx = ray.Direction.X; double dy = ray.Direction.Y; double dz = ray.Direction.Z; double x0 = ray.Position.X; double y0 = ray.Position.Y; double z0 = ray.Position.Z; double a = dx * dx * dx * dx + dy * dy * dy * dy + dz * dz * dz * dz; double b = 4.0 * dx * dx * dx * x0 + 4.0 * dy * dy * dy * y0 + 4.0 * dz * dz * dz; double c = 6.0 * dx * dx * x0 * x0 - 5.0 * dx * dx + 6.0 * dy * dy * y0 * y0 - 5.0 * dy * dy + 6.0 * dz * dz * z0 * z0 - 5.0 * dz * dz; double d = 4.0 * dx * x0 * x0 * x0 - 10.0 * dx * x0 + 4.0 * dy * y0 * y0 * y0 - 10.0 * dy * y0 + 4.0 * dz * z0 * z0 * z0; double e = x0 * x0 * x0 * x0 - 5.0 * x0 * x0 + y0 * y0 * y0 * y0 - 5.0 * y0 * y0 + z0 * z0 * z0 * z0 - 5.0 * z0 * z0 + 11.8; RealPolynomial poly = new RealPolynomial(a, b, c, d, e); //poly /= new RealPolynomial(100000); //poly.Normalize(); double ev = poly.Eval(1.0); double[] cof = poly.FindRoots(MathUtil.Epsilon, false); //double[] cof=RealPolynomial.SolveQuartic(a, b, c, d, e); bool found = false; t = double.MaxValue; foreach (var tt in RealPolynomial.SolveQuadric(a, b, c)) { if (tt > 1e-4 && tt < t) { t = tt; found = true; } } return(found); }
/// <summary> /// Intersects a line with a conic that is in standard position, that is, not rotated and /// centered at 0,0 /// </summary> /// <param name="con"></param> /// <param name="lin"></param> /// <returns>A list of parameters on line that is intersection points, or null if no intersections</returns> private static double[] ConicLineParametric(GeneralConic2d con, Line2d lin) { //We construct a matrix so that: conic is unrotated (B term=0) and line starts at origo and has length=1.0 //This is to improve stabillity of the equation double invlen = 1.0 / lin.Length; if (double.IsInfinity(invlen)) { return(null); //zero length line does not intersect } Transform2d tr = Transform2d.Translate(-lin.X1, -lin.Y1) * Transform2d.Rotate(-con.Rotation) * Transform2d.Scale(invlen); GeneralConic2d c = new GeneralConic2d(con); //copy for modification double x1 = lin.X2, y1 = lin.Y2; c.Transform(tr); tr.Apply(x1, y1, out x1, out y1, true); //transformed line end double t2 = y1 * y1 * c.C + x1 * x1 * c.A; double t1 = y1 * c.E + x1 * c.D; double t0 = c.F; double[] ts = RealPolynomial.SolveQuadric(t2, t1, t0); return(ts); /*double dx=lin.DX; * double dy=lin.DY; * double x0=lin.X1; * double y0=lin.Y1; * * double t2=con.C*dy*dy+con.A*dx*dx; * double t1=2*con.C*dy*y0+2*con.A*dx*x0+dy*con.E+con.D*dx; * double t0=con.C*y0*y0+con.E*y0+con.A*x0*x0+con.D*x0+con.F; * * return RealPolynomial.SolveQuadric(t2, t1, t0, 1e-9);*/ }
public static double[] HyperbolaLineParametric(Hyperbola2d hyp, Line2d lin) { // Computes intersection points with a hyperbola and a line // solved and created by Robert.P. 2013-02-11 // // solution is created by transforming system to hyperbola standard position, // and then solving the system x^2/a^2-y^2/b^2-1=0 , x=x0+t*dx and y=y0+t*dy (note that a is 1 in std. pos.) Transform2d tr = hyp.ToStandardPosition; //extract standard spaced line double x0, y0, x1, y1, dx, dy, b = hyp.Ratio; tr.Apply(lin.X1, lin.Y1, out x0, out y0, true); tr.Apply(lin.X2, lin.Y2, out x1, out y1, true); dx = x1 - x0; dy = y1 - y0; double t2 = -dy * dy + b * b * dx * dx; double t1 = -2 * dy * y0 + 2 * b * b * dx * x0; double t0 = -y0 * y0 + b * b * x0 * x0 - b * b; return(RealPolynomial.SolveQuadric(t2, t1, t0, 0.0)); }
public static Circle2d[] LinePointPoint(Line2d li, Point2d pt1, Point2d pt2) { // max two solutions // solution created by Robert.P. 2013-02-07 List <Circle2d> res = null; // transform problem so that we have a vertical line thru origo which simplifies stuff a lot Transform2d toorg = Transform2d.Translate(-li.X1, -li.Y1) * Transform2d.Rotate(-li.Angle + MathUtil.Deg90); Transform2d fromorg = toorg.Inversed; double i, j, k, l; toorg.Apply(pt1.X, pt1.Y, out i, out j, true); toorg.Apply(pt2.X, pt2.Y, out k, out l, true); double y2 = 2 * k - 2 * i; double y1 = 4 * i * l - 4 * j * k; double y0 = -2 * i * l * l - 2 * i * k * k + (2 * j * j + 2 * i * i) * k; double[] ys = RealPolynomial.SolveQuadric(y2, y1, y0); if (ys == null) { return(null); //no solutions } foreach (double y in ys) { double xx = (y * y - 2 * j * y + j * j + i * i) / (2 * i), yy = y; //TODO: what if vertical line double rad = Math.Abs(xx); fromorg.Apply(xx, yy, out xx, out yy, true); AddResult(ref res, xx, yy, rad); } return(MakeResult(res)); }
public static Circle2d[] LineLinePoint(Line2d lin1, Line2d lin2, Point2d pnt) { // Compute the 2 circles (or 1 in special cases) that tangents two lines and a point. // Solving for parameter t on the bisector vector between lines that have the same // distance to point as the radius for that t (given using radfac computed below) // Solution by Robert.P. 2013-02-14 List <Circle2d> res = null; Vector2d v1 = lin1.Direction; Vector2d v2 = lin2.Direction; Vector2d midvec; Point2d linint; double[] ts; linint = Intersect2d.LineLineAsPoint(lin1, lin2); //basepoint for midline vector if (linint == null) //special case for parallel lines { //use vector and base point on midpoint of radical line of circles midvec = v1; Line2d radlin = new Line2d(lin1.ClosestPoint(pnt), lin2.ClosestPoint(pnt)); linint = radlin.MidPoint; double r = radlin.Length * 0.5, i = pnt.X, j = pnt.Y, x0 = linint.X, y0 = linint.Y, dx = midvec.X, dy = midvec.Y; double tp2 = 1; //squared length of midlin => assume normalized double tp1 = 2 * (dy * y0 + dx * x0 - dy * j - dx * i); double tp0 = y0 * y0 - 2 * j * y0 - r * r + j * j + i * i + x0 * x0 - 2 * i * x0; ts = RealPolynomial.SolveQuadric(tp2, tp1, tp0, 0.0); if (ts == null) { return(null); } foreach (double t in ts) { Point2d center = linint + midvec * t; AddResult(ref res, center.X, center.Y, r); } } else //normal case with non-parallel lines { if (pnt.Location(lin1.Start, lin1.End) == pnt.Location(lin2.Start, lin2.End)) { v2 = -v2; //select correct bisector out of two (actually 4 but it does not matter if we solve for negative t) } midvec = v1.Bisect(v2); double radfac = Math.Sin(v1.AngleTo(v2) / 2.0); //multiplied with midvector t this gives radius of circle at that t //solve problem in space where pnt=origo Point2d org = new Point2d(linint.X - pnt.X, linint.Y - pnt.Y); double t2 = -radfac * radfac + 1; //// 1 for squared length of midlin => assume normalized double t1 = 2 * (midvec.Y * org.Y + midvec.X * org.X); double t0 = org.X * org.X + org.Y * org.Y; ts = RealPolynomial.SolveQuadric(t2, t1, t0, 0.0); if (ts == null) { return(null); } foreach (double t in ts) { Point2d center = linint + midvec * t; AddResult(ref res, center.X, center.Y, Math.Abs(t * radfac)); } } return(MakeResult(res)); }
public static Circle2d[] CircleCircleCircle(Circle2d ci1, Circle2d ci2, Circle2d ci3) { // see http://www.arcenciel.co.uk/geometry/ for explanation List <Circle2d> result = null; double r1, r2, r3, a, b, c, t, A, B, C; double fRadius, xc, yc, distc1c2; double[] roots; // if all circles concentric, there are no solutions distc1c2 = ci1.Center.Distance(ci2.Center); if (MathUtil.IsZero(distc1c2) && MathUtil.IsZero(ci2.Center.Distance(ci3.Center))) { return(null); } // make sure first 2 circles are not concentric // if so swap ci2,ci3 if (MathUtil.IsZero(distc1c2)) { var tmp = ci2; ci2 = ci3; ci3 = ci2; } // transform input so that ci1 is at origo and ci2 is on xaxis Transform2d trans = Transform2d.Translate(Point2d.Origo - ci1.Center) * Transform2d.Rotate(-ci1.Center.Angle(ci2.Center)); ci1 = new Circle2d(ci1); ci1.Transform(trans); ci2 = new Circle2d(ci2); ci2.Transform(trans); ci3 = new Circle2d(ci3); ci3.Transform(trans); // Negate the radii to get all combinations for (int iCase = 0; iCase < 8; ++iCase) { r1 = ((iCase & 1) == 0) ? ci1.Radius : -ci1.Radius; r2 = ((iCase & 2) == 0) ? ci2.Radius : -ci2.Radius; r3 = ((iCase & 4) == 0) ? ci3.Radius : -ci3.Radius; // special case where radii of first 2 circles are equal if (MathUtil.Equals(r1, r2)) { // Calculate x-cordinate of centre xc = ci2.X / 2.0; // if all radii are equal, there will be only one solution if (MathUtil.Equals(r1, r3)) { if (MathUtil.IsZero(ci3.Y)) { continue; } // get y-coordinate of centre yc = (ci3.X * ci3.X - 2.0 * xc * ci3.X + ci3.Y * ci3.Y) / (ci3.Y + ci3.Y); // compute radius A = 1; B = 2 * r1; C = r1 * r1 - xc * xc - yc * yc; roots = RealPolynomial.SolveQuadric(A, B, C); if (roots.Length > 0) { fRadius = roots[0]; if (fRadius <= 0.0) { //then try other root if (roots.Length > 1) { fRadius = roots[1]; if (fRadius <= 0.0) { continue; //no posetive roots } } } AddResult(ref result, xc, yc, fRadius); } } else { // compute constants double k = r1 * r1 - r3 * r3 + ci3.X * ci3.X + ci3.Y * ci3.Y - 2 * xc * ci3.X; A = 4 * ((r1 - r3) * (r1 - r3) - ci3.Y * ci3.Y); B = 4 * (k * (r1 - r3) - 2 * ci3.Y * ci3.Y * r1); C = 4 * xc * xc * ci3.Y * ci3.Y + k * k - 4 * ci3.Y * ci3.Y * r1 * r1; if (!MathUtil.IsZero(A)) { roots = RealPolynomial.SolveQuadric(A, B, C); foreach (double radius in roots) { yc = (2 * radius * (r1 - r3) + k) / (2 * ci3.Y); AddResult(ref result, xc, yc, radius); } } } continue; } //end special case of r1==r2 // Get constants a = 2 * (ci2.X * (r3 - r1) - ci3.X * (r2 - r1)); b = 2 * ci3.Y * (r1 - r2); c = (r2 - r1) * (ci3.X * ci3.X + ci3.Y * ci3.Y - (r3 - r1) * (r3 - r1)) - (r3 - r1) * (ci2.X * ci2.X - (r2 - r1) * (r2 - r1)); t = (ci2.X * ci2.X + r1 * r1 - r2 * r2) / 2.0; A = (r1 - r2) * (r1 - r2) * (a * a + b * b) - (ci2.X * ci2.X * b * b); B = 2 * (t * (r1 - r2) * (a * a + b * b) + a * c * ci2.X * (r1 - r2) - (r1 * ci2.X * ci2.X * b * b)); C = t * t * (a * a + b * b) + (2 * a * c * ci2.X * t) + (c * c * ci2.X * ci2.X) - (r1 * r1 * ci2.X * ci2.X * b * b); // Calculate radius roots = RealPolynomial.SolveQuadric(A, B, C); if (roots == null) { continue; } foreach (double radius in roots) { if (radius < minradius || radius > maxradius) { continue; } // get x coordinate of centre (x2 may not be zero) xc = (radius * (r1 - r2) + t) / ci2.X; // get y coordinate of centre. b should never be 0, as // r1=r2 is special case and y3 may not be zero yc = (-a * xc - c) / b; AddResult(ref result, xc, yc, radius); } } //convert back to original coordinate system by using the inverse //of the original matrix if (result != null) { trans = trans.Inversed; for (int l = 0; l < result.Count; l++) { result[l].Transform(trans); } return(result.ToArray()); } return(null); }
public static Circle2d[] CircleCircleLine(Circle2d ci1, Circle2d ci2, Line2d li) { // see http://www.arcenciel.co.uk/geometry/ for explanation List <Circle2d> result = null; double a1, b1, c1, t, r2, r3, a, b, c, u, s; double A, B, C, xc, yc; //transform input so that c1 is at origo and c2 is on xaxis Transform2d trans = Transform2d.Translate(Point2d.Origo - ci1.Center) * Transform2d.Rotate(-ci1.Center.Angle(ci2.Center)); ci1 = new Circle2d(ci1); ci1.Transform(trans); ci2 = new Circle2d(ci2); ci2.Transform(trans); li = new Line2d(li); li.Transform(trans); if (!li.ToEquation(out a1, out b1, out c1)) { return(null); //degenerate line } for (int signcase = 0; signcase < 8; ++signcase) { t = ((signcase & 1) == 0) ? 1 : -1; r2 = ((signcase & 2) == 0) ? ci1.Radius : -ci1.Radius; r3 = ((signcase & 4) == 0) ? ci2.Radius : -ci2.Radius; // Get constants a = 2 * (a1 * (r2 - r3) - ci2.X * t); b = 2 * b1 * (r2 - r3); c = 2 * c1 * (r2 - r3) + t * (r2 * r2 - r3 * r3 + ci2.X * ci2.X); if (!MathUtil.IsZero(b)) { u = b1 * c - b * c1; s = a1 * b - a * b1; A = t * t * b * b * (a * a + b * b) - b * b * s * s; B = 2 * (u * t * b * (a * a + b * b) + a * c * s * t * b - b * b * s * s * r2); C = u * u * (a * a + b * b) + 2 * a * c * s * u + c * c * s * s - b * b * s * s * r2 * r2; } else { u = a1 * c - a * c1; s = a * b1; A = a * a * (t * t * a * a - s * s); B = 2 * a * a * (u * t * a - s * s * r2); C = u * u * a * a + c * c * s * s - a * a * s * s * r2 * r2; } // Calculate radius double[] roots = RealPolynomial.SolveQuadric(A, B, C); if (roots != null) { foreach (double radius in roots) { if (radius < minradius || radius > maxradius) { continue; } // compute x coordinates of centers List <double> xsols = new List <double>(); if (!MathUtil.IsZero(ci2.X)) //circles are not concentric { xc = ((r2 + radius) * (r2 + radius) - (r3 + radius) * (r3 + radius) + ci2.X * ci2.X) / (2 * ci2.X); xsols.Add(xc); } else // If circles are concentric there can be 2 solutions for x { A = (a1 * a1 + b1 * b1); B = -2 * a1 * (radius * t - c1); C = (radius * t - c1) * (radius * t - c1) - b1 * b1 * (r2 + radius) * (r2 + radius); double[] roots2 = RealPolynomial.SolveQuadric(A, B, C); if (roots2 != null) { foreach (double x in roots2) { xsols.Add(x); } } } // now compute y coordinates from the calculated x:es // and input the final solution foreach (double x in xsols) { if (!MathUtil.IsZero(b1)) { yc = (-a1 * x - c1 + radius * t) / b1; } else { double ycSquare = (r2 + radius) * (r2 + radius) - (x * x); if (ycSquare < 0.0) { continue; } yc = Math.Sqrt(ycSquare); } AddResult(ref result, x, yc, radius); if (MathUtil.IsZero(b1)) { AddResult(ref result, x, -yc, radius); } } } } } //convert back to original coordinate system by using the inverse //of the original matrix if (result != null) { trans = trans.Inversed; for (int l = 0; l < result.Count; l++) { result[l].Transform(trans); } return(result.ToArray()); } return(null); }
public static Circle2d[] CircleLineLine(Circle2d ci, Line2d l1, Line2d l2) { // see http://www.arcenciel.co.uk/geometry/ for explanation List <Circle2d> result = null; //translate everyting so circle center at origo double dx = ci.X, dy = ci.Y; ci = new Circle2d(0, 0, ci.Radius); l1 = new Line2d(l1.X1 - dx, l1.Y1 - dy, l1.X2 - dx, l1.Y2 - dy); l2 = new Line2d(l2.X1 - dx, l2.Y1 - dy, l2.X2 - dx, l2.Y2 - dy); //if first line vertical, swap lines... if (MathUtil.Equals(l1.X1, l1.X2)) { var tmp = l1; l1 = l2; l2 = tmp; } //if first line still vertical, special case: if (MathUtil.Equals(l1.X1, l1.X2)) { double rad = (l1.X1 - l2.X1) / 2.0; double xcenter = (l1.X1 + l2.X1) / 2.0; double yc = Math.Sqrt((rad + ci.Radius) * (rad + ci.Radius) - xcenter * xcenter); AddResult(ref result, xcenter, ci.Y + yc, rad); AddResult(ref result, xcenter, ci.Y - yc, rad); } else { //now we know that first line is not vertical, and circle is centered at origo double a1, b1, c1, a2, b2, c2, u, w, s, a, b, c, xcenter, ycenter, t1, t2, r3; if (!l1.ToEquation(out a1, out b1, out c1)) { return(null); } if (!l2.ToEquation(out a2, out b2, out c2)) { return(null); } for (int signcase = 0; signcase < 8; signcase++) { t1 = ((signcase & 1) == 0) ? -1 : 1; t2 = ((signcase & 2) == 0) ? -1 : 1; r3 = ((signcase & 4) == 0) ? -ci.Radius : ci.Radius; u = (t1 * b2) - (t2 * b1); w = (b1 * c2) - (b2 * c1); s = (a1 * b2) - (a2 * b1); a = (u * u) - (2 * a1 * s * u * t1) + (t1 * t1 * s * s) - (b1 * b1 * s * s); b = 2.0 * ((u * w) + (c1 * a1 * s * u) - (a1 * s * t1 * w) - (c1 * t1 * s * s) - (r3 * b1 * b1 * s * s)); c = (w * w) + (2 * a1 * s * c1 * w) + (c1 * c1 * s * s) - (b1 * b1 * r3 * r3 * s * s); double[] roots = RealPolynomial.SolveQuadric(a, b, c); if (roots != null) { foreach (double radius in roots) { if (radius < minradius || radius > maxradius) { continue; } if (!MathUtil.IsZero(s)) { //non parallel lines, one center per root xcenter = (radius * u + w) / s; ycenter = ((-a1 * xcenter) - c1 + (radius * t1)) / b1; AddResult(ref result, xcenter, ycenter, radius); } else //parallel lines, two centers per root { a = t1 * t1; b = 2.0 * a1 * (c1 - (radius * t1)); c = ((radius * t1) - c1) * ((radius * t1) - c1) - (b1 * b2 * (r3 + radius) * (r3 + radius)); double[] roots2 = RealPolynomial.SolveQuadric(a, b, c); if (roots2 != null) { foreach (double x in roots2) { ycenter = (-a1 * x - c1 + radius * t1) / b1; AddResult(ref result, x, ycenter, radius); } } } } } } } //translate results back to original position if (result != null) { foreach (Circle2d c in result) { c.X += dx; c.Y += dy; } return(result.ToArray()); } return(null); }
/// <summary> /// Gets the line geometries, one or two lines. The type of the conic has to be /// Intersecting lines (2 results), Paralell lines (2 results) or Coincident lienes (1 result), /// otherwise the result is null. /// </summary> /// <returns></returns> public Line2d[] ToLines() { // Inspired by line extraction conmat.c from book Graphics Gems V double xx, yy; ConicType type = Type; Line2d tmplin; Transform2d tr; GeneralConic2d cpy; List <Line2d> res = null; double de = B * B * 0.25 - A * C; if (MathUtil.IsZero(A) && MathUtil.IsZero(B) && MathUtil.IsZero(C)) { //single line // compute endpoints of the line, avoiding division by zero res = new List <Line2d>(); if (Math.Abs(d) > Math.Abs(e)) { res.Add(new Line2d(-f / (d), 0.0, -(e + f) / (d), 1.0)); } else { res.Add(new Line2d(0.0, -f / (e), 1.0, -(d + f) / (e))); } } else { // two lines cpy = new GeneralConic2d(this); double a = cpy.a, b = cpy.b * 0.5, c = cpy.c, d = cpy.d * 0.5, e = cpy.e * 0.5, f = cpy.f; //get matrix coefficient // use the expression for phi that takes atan of the smallest argument double phi = (Math.Abs(b + b) < Math.Abs(a - c) ? Math.Atan((b + b) / (a - c)) : MathUtil.Deg360 - Math.Atan((a - c) / (b + b))) / 2.0; //phi = cpy.Rotation; if (MathUtil.IsZero(de)) { //parallel lines tr = Transform2d.Rotate(-phi); cpy.Transform(tr); a = cpy.A; b = cpy.B * 0.5; c = cpy.c; d = cpy.d * 0.5; e = cpy.e * 0.5; f = cpy.f; //get matrix coefficient if (Math.Abs(c) < Math.Abs(a)) // vertical { double[] xs = RealPolynomial.SolveQuadric(a, d, f); if (xs != null) { res = new List <Line2d>(); foreach (double x in xs) { tmplin = new Line2d(x, -1, x, 1); tmplin.Transform(tr.Inversed); //back to original spacxe res.Add(tmplin); } } } else //horizontal { double[] ys = RealPolynomial.SolveQuadric(c, e, f, 0.0); if (ys != null) { res = new List <Line2d>(); foreach (double y in ys) { tmplin = new Line2d(-1, y, 1, y); tmplin.Transform(tr.Inversed); res.Add(tmplin); } } } } //end parallel lines case else { //crossing lines Point2d center = Center; double rot = this.Rotation; tr = Transform2d.Translate(-center.X, -center.Y) * Transform2d.Rotate(-rot); cpy.Transform(tr); a = cpy.A; b = cpy.B * 0.5; c = cpy.c; d = cpy.c * 0.5; e = cpy.e * 0.5; f = cpy.f; res = new List <Line2d>(); xx = Math.Sqrt(Math.Abs(1.0 / a)); yy = Math.Sqrt(Math.Abs(1.0 / c)); tr = tr.Inversed; tmplin = new Line2d(-xx, -yy, xx, yy); tmplin.Transform(tr); res.Add(tmplin); tmplin = new Line2d(new Line2d(-xx, yy, xx, -yy)); tmplin.Transform(tr); res.Add(tmplin); } //end crossing lines case } //end two lines if (res == null || res.Count == 0) { return(null); } return(res.ToArray()); }