/// <summary> /// Checks an array of positions that purportedly correspond to a circular arc, to see /// whether the data is directed clockwise or not. No checks are made to confirm that /// the data really does correspond to a circular arc. /// </summary> /// <param name="pts">The positions defining an arc</param> /// <param name="center">The position of the centre of the circle that the arc lies on.</param> /// <returns>True if the data is ordered clockwise.</returns> public static bool IsClockwise(IPointGeometry[] pts, IPointGeometry center) { // To determine the direction, we must locate two successive // vertices that lie in the same quadrant (with respect to the // circle center). QuadVertex start = new QuadVertex(center, pts[0]); QuadVertex end = null; for (int i = 1; i < pts.Length; i++, start = end) { // Pick up the position at the end of the line segment. end = new QuadVertex(center, pts[i]); // If both ends of the segment are in the same quadrant, // see which one comes first. The result tells us whether // the curve is clockwise or not. if (start.Quadrant == end.Quadrant) { return(start.GetTanAngle() < end.GetTanAngle()); } } // Something has gone wrong if we got here! Debug.Assert(1 == 2); return(true); }
/// <summary> /// Checks an array of positions that purportedly correspond to a circular arc, to see /// whether the data is directed clockwise or not. No checks are made to confirm that /// the data really does correspond to a circular curve. /// </summary> /// <param name="pts">Positions on circular arc</param> /// <param name="center">The position of the centre of the circle that the curve lies on</param> /// <returns>True if the data is ordered clockwise.</returns> public static bool IsClockwise(IPosition[] pts, IPosition center) { if (pts.Length<2) return false; // To determine the direction, we must locate two successive // vertices that lie in the same quadrant (with respect to the // circle centre). QuadVertex start = new QuadVertex(center, pts[0]); QuadVertex end; for (int i=1; i<pts.Length; i++, start=end) { // Pick up the position at the end of the line segment end = new QuadVertex(center, pts[i]); // If both ends of the segment are in the same quadrant, // see which one comes first. The result tells us whether // the curve is clockwise or not. if (start.Quadrant == end.Quadrant) return (start.GetTanAngle() < end.GetTanAngle() ? true : false); } // Something has gone wrong if we got here! Debug.Assert(1==2); return true; }
/// <summary> /// Gets the most easterly position for this arc. /// </summary> /// <returns>The most easterly position</returns> internal override IPosition GetEastPoint() { // If the arc is a complete circle, just work it out the easy way. if (IsCircle) { return(m_Circle.GetEastPoint()); } // Determine where the east point is. It could be either the // BC, the EC, or the most easterly point of the circle. IPosition start = First; IPosition end = Second; char choice = (start.X > end.X ? 'S' : choice = 'E'); // But hold on. If the arc passes from the northeast to southeast // quadrant, we want the east point of the circle. IPosition c = m_Circle.Center; QuadVertex vs = new QuadVertex(c, start); QuadVertex ve = new QuadVertex(c, end); Quadrant qs = vs.Quadrant; Quadrant qe = ve.Quadrant; // If the BC & EC are in the same quadrant, the only way the // circle point can apply is if it goes all the way round. if (!(qs == qe && vs.GetTanAngle() < ve.GetTanAngle())) { // Determine whether the circle point applies. switch (qs) { case Quadrant.NE: { choice = 'C'; break; } case Quadrant.SE: break; case Quadrant.SW: { if (qe == Quadrant.SE) { choice = 'C'; } break; } case Quadrant.NW: { if (qe != Quadrant.NE) { choice = 'C'; } break; } } } if (choice == 'S') { return(start); } else if (choice == 'E') { return(end); } Debug.Assert(choice == 'C'); return(m_Circle.GetEastPoint()); }
public static IWindow GetExtent(ICircularArcGeometry g) { // If the curve is a complete circle, just define it the easy way. if (g.BC.IsCoincident(g.EC)) return CircleGeometry.GetExtent(g.Circle); IPosition bcp = g.BC; IPosition ecp = g.EC; IPosition centre = g.Circle.Center; // Initialize the window with the start location. Window win = new Window(bcp); // Expand using the end location win.Union(ecp); // If the curve is completely within one quadrant, we're done. QuadVertex bc = new QuadVertex(centre, bcp); QuadVertex ec = new QuadVertex(centre, ecp); Quadrant qbc = bc.Quadrant; Quadrant qec = ec.Quadrant; if (qbc == qec) { if (g.IsClockwise) { if (bc.GetTanAngle() < ec.GetTanAngle()) return win; } else { if (ec.GetTanAngle() < bc.GetTanAngle()) return win; } } // Get the window of the circle IWindow circle = CircleGeometry.GetExtent(g.Circle); // If the curve is anticlockwise, switch the quadrants for BC & EC if (!g.IsClockwise) { Quadrant temp = qbc; qbc = qec; qec = temp; } // Expand the window, depending on which quadrants the start & // end points fall in. The lack of breaks in the inner switches // is intentional (e.g. if start & end both fall in Quadrant.NorthEast, // the window we want is the complete circle, having checked above // for the case where the arc is JUST in Quadrant.NorthEast). // Define do-nothing values for the Union's below double wx = win.Min.X; double wy = win.Min.Y; if (qbc==Quadrant.NE) { switch (qec) { case Quadrant.NE: win.Union(wx, circle.Max.Y); goto case Quadrant.NW; case Quadrant.NW: win.Union(circle.Min.X, wy); goto case Quadrant.SW; case Quadrant.SW: win.Union(wx, circle.Min.Y); goto case Quadrant.SE; case Quadrant.SE: win.Union(circle.Max.X, wy); break; } } else if (qbc==Quadrant.SE) { switch (qec) { case Quadrant.SE: win.Union(circle.Max.X, wy); goto case Quadrant.NE; case Quadrant.NE: win.Union(wx, circle.Max.Y); goto case Quadrant.NW; case Quadrant.NW: win.Union(circle.Min.X, wy); goto case Quadrant.SW; case Quadrant.SW: win.Union(wx, circle.Min.Y); break; } } else if (qbc==Quadrant.SW) { switch (qec) { case Quadrant.SW: win.Union(wx, circle.Min.Y); goto case Quadrant.SE; case Quadrant.SE: win.Union(circle.Max.X, wy); goto case Quadrant.NE; case Quadrant.NE: win.Union(wx, circle.Max.Y); goto case Quadrant.NW; case Quadrant.NW: win.Union(circle.Min.X, wy); break; } } else if (qbc==Quadrant.NW) { switch (qec) { case Quadrant.NW: win.Union(circle.Min.X, wy); goto case Quadrant.SW; case Quadrant.SW: win.Union(wx, circle.Min.Y); goto case Quadrant.SE; case Quadrant.SE: win.Union(circle.Max.X, wy); goto case Quadrant.NE; case Quadrant.NE: win.Union(wx, circle.Max.Y); break; } } return win; }
public static IWindow GetExtent(ICircularArcGeometry g) { // If the curve is a complete circle, just define it the easy way. if (g.BC.IsCoincident(g.EC)) { return(CircleGeometry.GetExtent(g.Circle)); } IPosition bcp = g.BC; IPosition ecp = g.EC; IPosition centre = g.Circle.Center; // Initialize the window with the start location. Window win = new Window(bcp); // Expand using the end location win.Union(ecp); // If the curve is completely within one quadrant, we're done. QuadVertex bc = new QuadVertex(centre, bcp); QuadVertex ec = new QuadVertex(centre, ecp); Quadrant qbc = bc.Quadrant; Quadrant qec = ec.Quadrant; if (qbc == qec) { if (g.IsClockwise) { if (bc.GetTanAngle() < ec.GetTanAngle()) { return(win); } } else { if (ec.GetTanAngle() < bc.GetTanAngle()) { return(win); } } } // Get the window of the circle IWindow circle = CircleGeometry.GetExtent(g.Circle); // If the curve is anticlockwise, switch the quadrants for BC & EC if (!g.IsClockwise) { Quadrant temp = qbc; qbc = qec; qec = temp; } // Expand the window, depending on which quadrants the start & // end points fall in. The lack of breaks in the inner switches // is intentional (e.g. if start & end both fall in Quadrant.NorthEast, // the window we want is the complete circle, having checked above // for the case where the arc is JUST in Quadrant.NorthEast). // Define do-nothing values for the Union's below double wx = win.Min.X; double wy = win.Min.Y; if (qbc == Quadrant.NE) { switch (qec) { case Quadrant.NE: win.Union(wx, circle.Max.Y); goto case Quadrant.NW; case Quadrant.NW: win.Union(circle.Min.X, wy); goto case Quadrant.SW; case Quadrant.SW: win.Union(wx, circle.Min.Y); goto case Quadrant.SE; case Quadrant.SE: win.Union(circle.Max.X, wy); break; } } else if (qbc == Quadrant.SE) { switch (qec) { case Quadrant.SE: win.Union(circle.Max.X, wy); goto case Quadrant.NE; case Quadrant.NE: win.Union(wx, circle.Max.Y); goto case Quadrant.NW; case Quadrant.NW: win.Union(circle.Min.X, wy); goto case Quadrant.SW; case Quadrant.SW: win.Union(wx, circle.Min.Y); break; } } else if (qbc == Quadrant.SW) { switch (qec) { case Quadrant.SW: win.Union(wx, circle.Min.Y); goto case Quadrant.SE; case Quadrant.SE: win.Union(circle.Max.X, wy); goto case Quadrant.NE; case Quadrant.NE: win.Union(wx, circle.Max.Y); goto case Quadrant.NW; case Quadrant.NW: win.Union(circle.Min.X, wy); break; } } else if (qbc == Quadrant.NW) { switch (qec) { case Quadrant.NW: win.Union(circle.Min.X, wy); goto case Quadrant.SW; case Quadrant.SW: win.Union(wx, circle.Min.Y); goto case Quadrant.SE; case Quadrant.SE: win.Union(circle.Max.X, wy); goto case Quadrant.NE; case Quadrant.NE: win.Union(wx, circle.Max.Y); break; } } return(win); }
/// <summary> /// Gets the most easterly position for this arc. /// </summary> /// <returns>The most easterly position</returns> internal override IPosition GetEastPoint() { // If the arc is a complete circle, just work it out the easy way. if (IsCircle) return m_Circle.GetEastPoint(); // Determine where the east point is. It could be either the // BC, the EC, or the most easterly point of the circle. IPosition start = First; IPosition end = Second; char choice = (start.X > end.X ? 'S' : choice = 'E'); // But hold on. If the arc passes from the northeast to southeast // quadrant, we want the east point of the circle. IPosition c = m_Circle.Center; QuadVertex vs = new QuadVertex(c, start); QuadVertex ve = new QuadVertex(c, end); Quadrant qs = vs.Quadrant; Quadrant qe = ve.Quadrant; // If the BC & EC are in the same quadrant, the only way the // circle point can apply is if it goes all the way round. if (!(qs==qe && vs.GetTanAngle()<ve.GetTanAngle())) { // Determine whether the circle point applies. switch (qs) { case Quadrant.NE: { choice='C'; break; } case Quadrant.SE: break; case Quadrant.SW: { if (qe==Quadrant.SE) choice = 'C'; break; } case Quadrant.NW: { if (qe!=Quadrant.NE) choice = 'C'; break; } } } if (choice=='S') return start; else if (choice=='E') return end; Debug.Assert(choice=='C'); return m_Circle.GetEastPoint(); }