private Vector3D GetOrientation( EllipseParams topEllipse, EllipseParams botEllipse, Vector3D axisApproximation) { var topCircleBasis = EllipseHelper.CircleOrientation(topEllipse); var botCircleBasis = EllipseHelper.CircleOrientation(botEllipse); var topOrientation = GetOrientation(topCircleBasis, axisApproximation); var botOrientation = GetOrientation(botCircleBasis, axisApproximation); if (Vector3D.DotProduct(botOrientation, topOrientation) < 0) { botOrientation = -botOrientation; } var topPerimeter = EllipseHelper.ApproxPerimeter(topEllipse.XRadius, topEllipse.YRadius); var botPerimeter = EllipseHelper.ApproxPerimeter(botEllipse.XRadius, botEllipse.YRadius); //return result; if (topPerimeter > botPerimeter) { return(topOrientation); } else { return(botOrientation); } }
/// <summary> /// Computes 3D circle orientation given its projection as a 2D ellipse. /// </summary> /// <param name="ellipseParams">The parameters of the 2D ellipse</param> /// <returns>A tuple containing two basis vectors for the circle's plane. The second /// vector is correct up to the sign of its Z component.</returns> public static Tuple <Vector3D, Vector3D> CircleOrientation(EllipseParams ellipseParams) { Contract.Ensures(Contract.Result <Tuple <Vector3D, Vector3D> >() != null); var rotation = Matrix.Identity; rotation.Rotate(ellipseParams.Degrees); var a = rotation.Transform(new Vector(ellipseParams.XRadius, 0)); var b = rotation.Transform(new Vector(0, ellipseParams.YRadius)); // we swap a and b in case Y radius is larger than X radius // becuase we want a to be the major axis. if (ellipseParams.YRadius > ellipseParams.XRadius) { var temp = a; a = b; b = temp; } var result1 = new Vector3D(a.X, a.Y, 0); var result2 = new Vector3D(b.X, b.Y, Math.Sqrt(a.LengthSquared - b.LengthSquared)); return(Tuple.Create(result1, result2)); }
private Vector3D GetOrientation( EllipseParams botEllipse, Point[] spineApproximation, ref bool Reverse) { int nspine = spineApproximation.Length; Vector vnormal = new Vector(botEllipse.Center.X - spineApproximation[0].X, botEllipse.Center.Y + spineApproximation[0].Y); Vector vreverse = new Vector(botEllipse.Center.X - spineApproximation[spineApproximation.Length - 1].X, botEllipse.Center.Y + spineApproximation[spineApproximation.Length - 1].Y); Reverse = false; if (vnormal.Length > vreverse.Length) { Reverse = true; } Vector botAxis = new Vector(); if (!Reverse) { botAxis = new Vector(spineApproximation[1].X - spineApproximation[0].X, spineApproximation[0].Y - spineApproximation[1].Y); } else { botAxis = new Vector(spineApproximation[nspine - 2].X - spineApproximation[nspine - 1].X, spineApproximation[nspine - 1].Y - spineApproximation[nspine - 2].Y); } var botCircleBasis = EllipseHelper.CircleOrientation(botEllipse); var botOrientation = GetOrientation(botCircleBasis); Vector ApproxOrientationBotProj = new Vector(botOrientation.X, botOrientation.Y); if (ApproxOrientationBotProj * botAxis < 0) { botOrientation = -botOrientation; } //var topPerimeter = EllipseHelper.ApproxPerimeter(topEllipse.XRadius, topEllipse.YRadius); //var botPerimeter = EllipseHelper.ApproxPerimeter(botEllipse.XRadius, botEllipse.YRadius); //return result; //if (topPerimeter > botPerimeter) // return topOrientation; //else return(botOrientation); }
private Vector3D NewGetOrientation( Point[] topPnts, Point[] botPnts, EllipseParams topEllipse, EllipseParams botEllipse, Vector3D axisApproximation) { double mx = 0.0; double my = 0.0; foreach (Point pnt in topPnts) { mx += pnt.X; my += pnt.Y; } mx /= topPnts.Length; my /= topPnts.Length; double Cxx = 0.0; double Cyy = 0.0; double Cxy = 0.0; foreach (Point pnt in topPnts) { Cxx += Math.Pow(pnt.X - mx, 2.0); Cyy += Math.Pow(pnt.Y - my, 2.0); Cxy += (pnt.X - mx) * (pnt.Y - my); } Cxx *= 1.0 / topPnts.Length; Cyy *= 1.0 / topPnts.Length; Cxy *= 1.0 / topPnts.Length; double trC = Cxx + Cyy; double detC = Cxx * Cyy - Cxy * Cxy; double l1 = 0.5 * trC + Math.Sqrt(0.25 * trC * trC - detC); double l2 = 0.5 * trC - Math.Sqrt(0.25 * trC * trC - detC); double a1 = 2 * Math.Sqrt(l1); double a2 = 2 * Math.Sqrt(l2); /*if (a1 < a2){ * double temp = a1; * a1 = a2; * a2 = temp; * }*/ Vector3D ApproxOrientation1 = new Vector3D(Math.Sqrt(a1 * a1 - 4 * Cxx) / a1, Math.Sqrt(a1 * a1 - 4 * Cyy) / a1, a2 / a1); mx = 0.0; my = 0.0; foreach (Point pnt in botPnts) { mx += pnt.X; my += pnt.Y; } mx /= topPnts.Length; my /= topPnts.Length; Cxx = 0.0; Cyy = 0.0; Cxy = 0.0; foreach (Point pnt in botPnts) { Cxx += Math.Pow(pnt.X - mx, 2.0); Cyy += Math.Pow(pnt.Y - my, 2.0); Cxy += (pnt.X - mx) * (pnt.Y - my); } Cxx *= 1.0 / botPnts.Length; Cyy *= 1.0 / botPnts.Length; Cxy *= 1.0 / botPnts.Length; trC = Cxx + Cyy; detC = Cxx * Cyy - Cxy * Cxy; l1 = 0.5 * trC + Math.Sqrt(0.25 * trC * trC - detC); l2 = 0.5 * trC - Math.Sqrt(0.25 * trC * trC - detC); a1 = 2 * Math.Sqrt(l1); a2 = 2 * Math.Sqrt(l2); /*if (a1 < a2){ * double temp = a1; * a1 = a2; * a2 = temp; * }*/ Vector3D ApproxOrientation2 = new Vector3D(Math.Sqrt(a1 * a1 - 4 * Cxx) / a1, Math.Sqrt(a1 * a1 - 4 * Cyy) / a1, a2 / a1); short sign = 1; if (Vector3D.DotProduct(ApproxOrientation2, ApproxOrientation1) < 0) { sign = -1; } Vector3D ApproxOrientation = 0.5 * (ApproxOrientation1.Normalized() + sign * ApproxOrientation2.Normalized()); return(ApproxOrientation.Normalized()); }
private Vector3D NewGetOrientation( Point[] topPnts, Point[] botPnts, EllipseParams topEllipse, EllipseParams botEllipse, Point[] spineApproximation, ref bool Reverse) { /*MessageBox.Show(String.Format("Ellipse Center : ({0},{1})", botEllipse.Center.X, botEllipse.Center.Y)); * MessageBox.Show(String.Format("Ellipse Center : ({0},{1})", spineApproximation[0].X, -spineApproximation[0].Y)); * MessageBox.Show(String.Format("Ellipse Center : ({0},{1})", spineApproximation[spineApproximation.Length - 1].X, -spineApproximation[spineApproximation.Length - 1].Y));*/ int nspine = spineApproximation.Length; // Here we check whether the bottom feature curve is the start of the computed spine or the spine is reversed Vector vnormal = new Vector(botEllipse.Center.X - spineApproximation[0].X, botEllipse.Center.Y + spineApproximation[0].Y); Vector vreverse = new Vector(botEllipse.Center.X - spineApproximation[spineApproximation.Length - 1].X, botEllipse.Center.Y + spineApproximation[spineApproximation.Length - 1].Y); Reverse = false; if (vnormal.Length > vreverse.Length) { Reverse = true; } Vector botAxis = new Vector(); Vector topAxis = new Vector(); if (!Reverse) { botAxis = new Vector(spineApproximation[1].X - spineApproximation[0].X, spineApproximation[0].Y - spineApproximation[1].Y); topAxis = new Vector(spineApproximation[nspine - 1].X - spineApproximation[nspine - 2].X, spineApproximation[nspine - 2].Y - spineApproximation[nspine - 1].Y); } else { topAxis = new Vector(spineApproximation[0].X - spineApproximation[1].X, spineApproximation[1].Y - spineApproximation[0].Y); botAxis = new Vector(spineApproximation[nspine - 2].X - spineApproximation[nspine - 1].X, spineApproximation[nspine - 1].Y - spineApproximation[nspine - 2].Y); } //MessageBox.Show(String.Format("Bottom Vector:{0}, {1}", botAxis.X, botAxis.Y)); //MessageBox.Show(String.Format("Top Vector:{0}, {1}", topAxis.X, topAxis.Y)); double mx = 0.0; double my = 0.0; foreach (Point pnt in topPnts) { mx += pnt.X; my += pnt.Y; } mx /= topPnts.Length; my /= topPnts.Length; double Cxx = 0.0; double Cyy = 0.0; double Cxy = 0.0; foreach (Point pnt in topPnts) { Cxx += Math.Pow(pnt.X - mx, 2.0); Cyy += Math.Pow(pnt.Y - my, 2.0); Cxy += (pnt.X - mx) * (pnt.Y - my); } Cxx /= topPnts.Length; Cyy /= topPnts.Length; Cxy /= topPnts.Length; double trC = Cxx + Cyy; double detC = Cxx * Cyy - Cxy * Cxy; double l1 = 0.5 * trC + Math.Sqrt(0.25 * trC * trC - detC); double l2 = 0.5 * trC - Math.Sqrt(0.25 * trC * trC - detC); double a1 = 2 * Math.Sqrt(l1); double a2 = 2 * Math.Sqrt(l2); Vector3D ApproxOrientationTop = new Vector3D(Math.Sqrt(a1 * a1 - 4 * Cxx) / a1, Math.Sqrt(a1 * a1 - 4 * Cyy) / a1, a2 / a1); Vector ApproxOrientationTopProj = new Vector(ApproxOrientationTop.X, ApproxOrientationTop.Y); if (ApproxOrientationTopProj * topAxis < 0) { ApproxOrientationTop = -ApproxOrientationTop; } mx = 0; //botEllipse.Center.X; my = 0; // botEllipse.Center.Y; /*MessageBox.Show(String.Format("Number of points of bottom feature : {0}", botPnts.Length));*/ foreach (Point pnt in botPnts) { mx += pnt.X; my += pnt.Y; } mx /= topPnts.Length; my /= topPnts.Length; Cxx = 0.0; Cyy = 0.0; Cxy = 0.0; foreach (Point pnt in botPnts) { Cxx += Math.Pow(pnt.X - mx, 2.0); Cyy += Math.Pow(pnt.Y - my, 2.0); Cxy += (pnt.X - mx) * (pnt.Y - my); } Cxx /= botPnts.Length; Cyy /= botPnts.Length; Cxy /= botPnts.Length; trC = Cxx + Cyy; detC = Cxx * Cyy - Cxy * Cxy; l1 = 0.5 * trC + Math.Sqrt(0.25 * trC * trC - detC); l2 = 0.5 * trC - Math.Sqrt(0.25 * trC * trC - detC); //MessageBox.Show(String.Format("({0}, {1}), ({2}, {3})", 2*botEllipse.XRadius, 2*botEllipse.YRadius, 2 * Math.Sqrt(l1), 2 * Math.Sqrt(l2))); a1 = 2 * Math.Sqrt(l1); a2 = 2 * Math.Sqrt(l2); if (a1 < a2) { double temp = a1; a1 = a2; a2 = temp; } Vector3D ApproxOrientationBot = new Vector3D(Math.Sqrt(a1 * a1 - 4 * Cxx) / a1, Math.Sqrt(a1 * a1 - 4 * Cyy) / a1, a2 / a1); Vector ApproxOrientationBotProj = new Vector(ApproxOrientationBot.X, ApproxOrientationBot.Y); if (ApproxOrientationBotProj * botAxis < 0) { ApproxOrientationBot = -ApproxOrientationBot; } //MessageBox.Show(String.Format("Top Vector:{0}, {1}", botAxis.X, botAxis.Y)); //MessageBox.Show(String.Format("Bottom Vector Estimation :{0}, {1}, {2}, {3}", ApproxOrientationBot.X, ApproxOrientationBot.Y, ApproxOrientationBot.Z, ApproxOrientationBot.Length)); Vector3D ApproxOrientation = 0.5 * (ApproxOrientationTop.Normalized() + ApproxOrientationBot.Normalized()); //return ApproxOrientation; /*if (Reverse) * { * MessageBox.Show("Reverse!!!"); * return -ApproxOrientationBot.Normalized(); * }*/ //else return(ApproxOrientationBot.Normalized()); }