/// <summary> /// Draws an arc. /// </summary> public void Draw(C2DArc Arc, Graphics graphics, Pen pen) { C2DRect Rect = new C2DRect(); int nStartAngle = 0; int nSweepAngle = 0; GetArcParameters(Arc, Rect, ref nStartAngle, ref nSweepAngle); if (nSweepAngle == 0) { nSweepAngle = 1; } int Width = (int)Rect.Width(); if (Width == 0) { Width = 1; } int Height = (int)Rect.Height(); if (Height == 0) { Height = 1; } graphics.DrawArc(pen, (int)Rect.TopLeft.x, (int)Rect.BottomRight.y, Width, Height, nStartAngle, nSweepAngle); }
/// <summary> /// Gets the area. /// </summary> public double GetArea() { double dArea = 0; for (int i = 0; i < Lines.Count; i++) { C2DPoint pt1 = _Lines[i].GetPointFrom(); C2DPoint pt2 = _Lines[i].GetPointTo(); dArea += pt1.x * pt2.y - pt2.x * pt1.y; } dArea = dArea / 2.0; for (int i = 0; i < Lines.Count; i++) { if (_Lines[i] is C2DArc) { C2DArc Arc = _Lines[i] as C2DArc; C2DSegment Seg = new C2DSegment(Arc); dArea += Seg.GetAreaSigned(); } } return(Math.Abs(dArea)); }
/// <summary> /// Assignment. /// </summary> /// <param name="other">The arc to set this to.</param> public void Set(C2DArc other) { Line.Set(other.Line); Radius = other.Radius; CentreOnRight = other.CentreOnRight; ArcOnRight = other.ArcOnRight; }
/// <summary> /// Gets the parameters required to draw an arc. /// </summary> private void GetArcParameters(C2DArc Arc, C2DRect Rect, ref int nStartAngle, ref int nSweepAngle) { C2DPoint Centre = Arc.GetCircleCentre(); Rect.Set(Centre.x - Arc.Radius, Centre.y + Arc.Radius, Centre.x + Arc.Radius, Centre.y - Arc.Radius); ScaleAndOffSet(Rect.TopLeft); ScaleAndOffSet(Rect.BottomRight); ScaleAndOffSet(Centre); // CR 19-1-09 C2DPoint bottomRightTemp = new C2DPoint(Rect.BottomRight); // to make valid // CR 11-3-09 Rect.BottomRight.Set(Rect.TopLeft); // to make valid // CR 11-3-09 Rect.ExpandToInclude(bottomRightTemp); // to make valid // CR 11-3-09 C2DPoint pt1 = Arc.Line.GetPointFrom(); C2DPoint pt2 = Arc.Line.GetPointTo(); this.ScaleAndOffSet(pt1); this.ScaleAndOffSet(pt2); C2DVector vec1 = new C2DVector(Centre, pt1); C2DVector vec2 = new C2DVector(Centre, pt2); C2DVector vecx = new C2DVector(100, 0); // x - axis double dStartAngle = vecx.AngleToLeft(vec1) * Constants.conDegreesPerRadian; double dSweepAngle = 0; bool bAlreadyFlipped = Scale.x * Scale.y < 0; if (Arc.ArcOnRight ^ bAlreadyFlipped) { dSweepAngle = vec1.AngleToLeft(vec2) * Constants.conDegreesPerRadian; } else { dSweepAngle = -vec1.AngleToRight(vec2) * Constants.conDegreesPerRadian; } nStartAngle = (int)dStartAngle; if (nStartAngle == 360) { nStartAngle = 0; } nSweepAngle = (int)dSweepAngle; }
/// <summary> /// True if this line crosses the other line, returns the intersection pt. /// </summary> /// <param name="Other">The other line to test.</param> /// <param name="IntersectionPts">Output. The intersection points.</param> public override bool Crosses(C2DLineBase Other, List <C2DPoint> IntersectionPts) { if (Other is C2DLine) { return(Crosses(Other as C2DLine, IntersectionPts)); } else if (Other is C2DArc) { C2DArc Arc = Other as C2DArc; return(Arc.Crosses(this, IntersectionPts)); } else { Debug.Assert(false, "Invalid Line type"); return(false); } }
/// <summary> /// Returns the distance from this to the other line. /// </summary> /// <param name="Other">The other line.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> /// <param name="ptOnOther">Output. The closest point on the other line.</param> public override double Distance(C2DLineBase Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { if (Other is C2DLine) { return(Distance(Other as C2DLine, ptOnThis, ptOnOther)); } else if (Other is C2DArc) { C2DArc Arc = Other as C2DArc; return(Arc.Distance(this, ptOnThis, ptOnOther)); } else { Debug.Assert(false, "Invalid Hole type"); return(0); } }
/// <summary> /// Returns the projection of this onto the line provided, given as the interval on /// (or off) the line. Interval given as distance from the start of the line. /// </summary> /// <param name="TestLine">The projection line.</param> /// <param name="Interval">The interval to recieve the result.</param> public override void Project(C2DLine TestLine, CInterval Interval) { C2DArc ThisCopy = new C2DArc(this); C2DLine LineCopy = new C2DLine(TestLine); double dAng = LineCopy.vector.AngleFromNorth(); LineCopy.vector.TurnLeft(dAng); ThisCopy.RotateToRight(-dAng, LineCopy.point); C2DRect rect = new C2DRect(); ThisCopy.GetBoundingRect(rect); Interval.dMax = rect.GetTop() - LineCopy.point.y; Interval.dMin = Interval.dMax; Interval.ExpandToInclude(rect.GetBottom() - LineCopy.point.y); }
/// <summary> /// Arc to a new point. /// </summary> /// <param name="Point">The point to go to.</param> /// <param name="dRadius">The radius.</param> /// <param name="bCentreOnRight">Indicates whether the centre of the arc is to the right of the line.</param> /// <param name="bArcOnRight">indicates whether the curve is to the right i.e. anti-clockwise.</param> public void LineTo(C2DPoint Point, double dRadius, bool bCentreOnRight, bool bArcOnRight) { if (Lines.Count == 0) return; C2DArc pLine = new C2DArc( Lines[Lines.Count - 1].GetPointTo(), Point, dRadius, bCentreOnRight, bArcOnRight); if (Lines.Count == 1 && Lines[0] is C2DLine && Lines[0].GetPointTo().PointEqualTo(Lines[0].GetPointFrom())) // CR 19-1-09 { Lines[0] = pLine; } else { Lines.Add(pLine); } }
/// <summary> /// Returns the projection of this onto the vector provided, given as the interval on /// (or off) the vector. Interval given as distance from the start of the vector. /// The vector is equivalent to a line from (0, 0). /// </summary> /// <param name="Vector">The projection vector.</param> /// <param name="Interval">The interval to recieve the result.</param> public override void Project(C2DVector Vector, CInterval Interval) { C2DArc ThisCopy = new C2DArc(this); C2DVector VecCopy = new C2DVector(Vector); double dAng = VecCopy.AngleFromNorth(); VecCopy.TurnLeft(dAng); ThisCopy.RotateToRight(-dAng, new C2DPoint(0, 0)); C2DRect rect = new C2DRect(); ThisCopy.GetBoundingRect(rect); Interval.dMax = rect.GetTop() - VecCopy.j; Interval.dMin = Interval.dMax; Interval.ExpandToInclude(rect.GetBottom() - VecCopy.j); }
/// <summary> /// Arc to a new point. /// </summary> /// <param name="Point">The point to go to.</param> /// <param name="dRadius">The radius.</param> /// <param name="bCentreOnRight">Indicates whether the centre of the arc is to the right of the line.</param> /// <param name="bArcOnRight">indicates whether the curve is to the right i.e. anti-clockwise.</param> public void LineTo(C2DPoint Point, double dRadius, bool bCentreOnRight, bool bArcOnRight) { if (Lines.Count == 0) { return; } C2DArc pLine = new C2DArc(Lines[Lines.Count - 1].GetPointTo(), Point, dRadius, bCentreOnRight, bArcOnRight); if (Lines.Count == 1 && Lines[0] is C2DLine && Lines[0].GetPointTo().PointEqualTo(Lines[0].GetPointFrom())) // CR 19-1-09 { Lines[0] = pLine; } else { Lines.Add(pLine); } }
/// <summary> /// Draws an arc. /// </summary> public void Draw(C2DArc Arc, Graphics graphics, Pen pen) { C2DRect Rect = new C2DRect(); int nStartAngle = 0; int nSweepAngle = 0; GetArcParameters(Arc, Rect, ref nStartAngle, ref nSweepAngle); if (nSweepAngle == 0) nSweepAngle = 1; int Width = (int)Rect.Width(); if (Width == 0) Width = 1; int Height = (int)Rect.Height(); if (Height == 0) Height = 1; graphics.DrawArc(pen, (int)Rect.TopLeft.x, (int)Rect.BottomRight.y, Width, Height, nStartAngle, nSweepAngle); }
/// <summary> /// True if this crosses a curved line. /// </summary> /// <param name="Other">The other arc.</param> /// <param name="IntersectionPts">The interection point list to recieve the result.</param> public bool Crosses(C2DArc Other, List <C2DPoint> IntersectionPts) { C2DCircle TestCircleThis = new C2DCircle(GetCircleCentre(), Radius); C2DCircle TestCircleOther = new C2DCircle(Other.GetCircleCentre(), Other.Radius); List <C2DPoint> IntPtsTemp = new List <C2DPoint>(); if (TestCircleThis.Crosses(TestCircleOther, IntPtsTemp)) { for (int i = IntPtsTemp.Count - 1; i >= 0; i--) { if ((Line.IsOnRight(IntPtsTemp[i]) ^ ArcOnRight) || Other.Line.IsOnRight(IntPtsTemp[i]) ^ Other.ArcOnRight || IntPtsTemp[i].PointEqualTo(Line.point) || IntPtsTemp[i].PointEqualTo(Line.GetPointTo()) || IntPtsTemp[i].PointEqualTo(Other.GetPointFrom()) || IntPtsTemp[i].PointEqualTo(Other.GetPointTo())) { IntPtsTemp.RemoveAt(i); } } if (IntPtsTemp.Count == 0) { return(false); } else { IntersectionPts.InsertRange(0, IntPtsTemp); // IntPtsTemp.CopyTo( IntersectionPts ); // (*IntersectionPts) << IntPtsTemp; return(true); } } else { return(false); } }
/// <summary> /// Creates a random shape. /// </summary> /// <param name="cBoundary">The boundary.</param> /// <param name="nMinPoints">The minimum points.</param> /// <param name="nMaxPoints">The maximum points.</param> public bool CreateRandom(C2DRect cBoundary, int nMinPoints, int nMaxPoints) { C2DPolygon Poly = new C2DPolygon(); if (!Poly.CreateRandom(cBoundary, nMinPoints, nMaxPoints)) { return(false); } CRandomNumber rCenOnRight = new CRandomNumber(0, 1); this.Set(Poly); for (int i = 0; i < Lines.Count; i++) { C2DLineBase pLine = Lines[i]; bool bCenOnRight = (rCenOnRight.GetInt() > 0); double dLength = pLine.GetLength(); CRandomNumber Radius = new CRandomNumber(dLength, dLength * 3); C2DArc pNew = new C2DArc(pLine.GetPointFrom(), pLine.GetPointTo(), Radius.Get(), bCenOnRight, !bCenOnRight); if (!this.Crosses(pNew)) { Lines[i] = pNew; pNew.GetBoundingRect(LineRects[i]); BoundingRect.ExpandToInclude(LineRects[i]); } } // this.MakeLineRects(); // this.MakeBoundingRect(); return(true); }
/// <summary> /// Constructor. /// </summary> /// <param name="ArcOther">The other arc.</param> public C2DSegment(C2DArc ArcOther) { Arc.Set(ArcOther); }
/// <summary> /// The distance between this and another arc. /// </summary> /// <param name="Other">The test point.</param> /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param> /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param> public double Distance(C2DArc Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { List <C2DPoint> IntPts1 = new List <C2DPoint>(); List <C2DPoint> IntPts2 = new List <C2DPoint>(); C2DPoint ptThisCen = new C2DPoint(GetCircleCentre()); C2DPoint ptOtherCen = new C2DPoint(Other.GetCircleCentre()); C2DCircle CircleThis = new C2DCircle(ptThisCen, Radius); C2DCircle CircleOther = new C2DCircle(ptOtherCen, Other.Radius); if (CircleThis.Crosses(CircleOther, IntPts1)) { for (int i = 0; i < IntPts1.Count; i++) { if ((Line.IsOnRight(IntPts1[i]) == ArcOnRight) && (Other.Line.IsOnRight(IntPts1[i]) == Other.ArcOnRight)) { ptOnThis.Set(IntPts1[i]); ptOnOther.Set(IntPts1[i]); return(0); } } IntPts1.Clear(); } C2DLine LineCenToOther = new C2DLine(); LineCenToOther.point = new C2DPoint(ptThisCen); LineCenToOther.vector = new C2DVector(ptThisCen, ptOtherCen); LineCenToOther.GrowFromCentre(Math.Max(Radius, Other.Radius) * 10); double dMinDist = 1.7E308; double dDist = 0; if (Crosses(LineCenToOther, IntPts1) && Other.Crosses(LineCenToOther, IntPts2)) { for (int i = 0; i < IntPts1.Count; i++) { for (int j = 0; j < IntPts2.Count; j++) { dDist = IntPts1[i].Distance(IntPts2[j]); if (dDist < dMinDist) { ptOnThis.Set(IntPts1[i]); ptOnOther.Set(IntPts2[j]); dMinDist = dDist; } } } } C2DPoint ptOnThisTemp = new C2DPoint(); dDist = Distance(Other.GetPointFrom(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointFrom()); dMinDist = dDist; } dDist = Distance(Other.GetPointTo(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointTo()); dMinDist = dDist; } C2DPoint ptOnOtherTemp = new C2DPoint(); dDist = Other.Distance(GetPointFrom(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set(GetPointFrom()); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; } dDist = Other.Distance(GetPointTo(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set(GetPointTo()); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; } return(dMinDist); }
/// <summary> /// Contructor. /// </summary> /// <param name="Other">Arc to which this will be assigned.</param> public C2DArc(C2DArc Other) { Set(Other); }
/// <summary> /// Creates a random shape. /// </summary> /// <param name="cBoundary">The boundary.</param> /// <param name="nMinPoints">The minimum points.</param> /// <param name="nMaxPoints">The maximum points.</param> public bool CreateRandom(C2DRect cBoundary, int nMinPoints, int nMaxPoints) { C2DPolygon Poly = new C2DPolygon(); if (!Poly.CreateRandom(cBoundary, nMinPoints, nMaxPoints)) return false; CRandomNumber rCenOnRight = new CRandomNumber(0, 1); this.Set( Poly ); for (int i = 0 ; i < Lines.Count; i ++) { C2DLineBase pLine = Lines[i]; bool bCenOnRight = (rCenOnRight.GetInt() > 0 ); double dLength = pLine.GetLength(); CRandomNumber Radius = new CRandomNumber(dLength , dLength * 3); C2DArc pNew = new C2DArc( pLine.GetPointFrom(), pLine.GetPointTo(), Radius.Get(), bCenOnRight, !bCenOnRight); if (!this.Crosses( pNew )) { Lines[i] = pNew; pNew.GetBoundingRect(LineRects[i]); BoundingRect.ExpandToInclude(LineRects[i]); } } // this.MakeLineRects(); // this.MakeBoundingRect(); return true; }
/// <summary> /// Returns the projection of this onto the line provided, given as the interval on /// (or off) the line. Interval given as distance from the start of the line. /// </summary> /// <param name="TestLine">The projection line.</param> /// <param name="Interval">The interval to recieve the result.</param> public override void Project(C2DLine TestLine, CInterval Interval) { C2DArc ThisCopy = new C2DArc(this); C2DLine LineCopy = new C2DLine(TestLine); double dAng = LineCopy.vector.AngleFromNorth(); LineCopy.vector.TurnLeft(dAng); ThisCopy.RotateToRight( -dAng, LineCopy.point); C2DRect rect = new C2DRect(); ThisCopy.GetBoundingRect( rect); Interval.dMax = rect.GetTop() - LineCopy.point.y; Interval.dMin = Interval.dMax; Interval.ExpandToInclude(rect.GetBottom() - LineCopy.point.y); }
/// <summary> /// True if this crosses a curved line. /// </summary> /// <param name="Other">The other arc.</param> /// <param name="IntersectionPts">The interection point list to recieve the result.</param> public bool Crosses(C2DArc Other, List<C2DPoint> IntersectionPts) { C2DCircle TestCircleThis = new C2DCircle (GetCircleCentre(), Radius); C2DCircle TestCircleOther= new C2DCircle (Other.GetCircleCentre(), Other.Radius); List<C2DPoint> IntPtsTemp = new List<C2DPoint>(); if (TestCircleThis.Crosses(TestCircleOther, IntPtsTemp)) { for (int i = IntPtsTemp.Count - 1; i >= 0 ; i--) { if ((Line.IsOnRight(IntPtsTemp[i]) ^ ArcOnRight) || Other.Line.IsOnRight(IntPtsTemp[i]) ^ Other.ArcOnRight || IntPtsTemp[i].PointEqualTo( Line.point) || IntPtsTemp[i].PointEqualTo( Line.GetPointTo()) || IntPtsTemp[i].PointEqualTo( Other.GetPointFrom()) || IntPtsTemp[i].PointEqualTo( Other.GetPointTo())) { IntPtsTemp.RemoveAt(i); } } if (IntPtsTemp.Count == 0) return false; else { IntersectionPts.InsertRange(0, IntPtsTemp); // IntPtsTemp.CopyTo( IntersectionPts ); // (*IntersectionPts) << IntPtsTemp; return true; } } else { return false; } }
/// <summary> /// Returns the projection of this onto the vector provided, given as the interval on /// (or off) the vector. Interval given as distance from the start of the vector. /// The vector is equivalent to a line from (0, 0). /// </summary> /// <param name="Vector">The projection vector.</param> /// <param name="Interval">The interval to recieve the result.</param> public override void Project(C2DVector Vector, CInterval Interval) { C2DArc ThisCopy = new C2DArc(this); C2DVector VecCopy = new C2DVector(Vector); double dAng = VecCopy.AngleFromNorth(); VecCopy.TurnLeft(dAng); ThisCopy.RotateToRight( -dAng, new C2DPoint(0, 0)); C2DRect rect = new C2DRect(); ThisCopy.GetBoundingRect( rect); Interval.dMax = rect.GetTop() - VecCopy.j; Interval.dMin = Interval.dMax; Interval.ExpandToInclude( rect.GetBottom() - VecCopy.j ); }
/// <summary> /// Gets the parameters required to draw an arc. /// </summary> private void GetArcParameters(C2DArc Arc, C2DRect Rect, ref int nStartAngle, ref int nSweepAngle) { C2DPoint Centre = Arc.GetCircleCentre(); Rect.Set(Centre.x - Arc.Radius, Centre.y + Arc.Radius, Centre.x + Arc.Radius, Centre.y - Arc.Radius); ScaleAndOffSet(Rect.TopLeft); ScaleAndOffSet(Rect.BottomRight); ScaleAndOffSet(Centre); // CR 19-1-09 C2DPoint bottomRightTemp = new C2DPoint(Rect.BottomRight); // to make valid // CR 11-3-09 Rect.BottomRight.Set(Rect.TopLeft); // to make valid // CR 11-3-09 Rect.ExpandToInclude(bottomRightTemp); // to make valid // CR 11-3-09 C2DPoint pt1 = Arc.Line.GetPointFrom(); C2DPoint pt2 = Arc.Line.GetPointTo(); this.ScaleAndOffSet(pt1); this.ScaleAndOffSet(pt2); C2DVector vec1 = new C2DVector(Centre, pt1); C2DVector vec2 = new C2DVector(Centre, pt2); C2DVector vecx = new C2DVector(100, 0); // x - axis double dStartAngle = vecx.AngleToLeft(vec1) * Constants.conDegreesPerRadian; double dSweepAngle = 0; bool bAlreadyFlipped = Scale.x * Scale.y < 0; if (Arc.ArcOnRight ^ bAlreadyFlipped) dSweepAngle = vec1.AngleToLeft(vec2) * Constants.conDegreesPerRadian; else dSweepAngle = -vec1.AngleToRight(vec2) * Constants.conDegreesPerRadian; nStartAngle = (int)dStartAngle; if (nStartAngle == 360) nStartAngle = 0; nSweepAngle = (int)dSweepAngle; }
/// <summary> /// The distance between this and another arc. /// </summary> /// <param name="Other">The test point.</param> /// <param name="ptOnThis">The closest point on this to the other as a returned value.</param> /// <param name="ptOnOther">The closest point on the other to this as a returned value.</param> public double Distance(C2DArc Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { List<C2DPoint> IntPts1 = new List<C2DPoint>(); List<C2DPoint> IntPts2 = new List<C2DPoint>(); C2DPoint ptThisCen = new C2DPoint( GetCircleCentre() ); C2DPoint ptOtherCen = new C2DPoint(Other.GetCircleCentre()); C2DCircle CircleThis = new C2DCircle( ptThisCen, Radius); C2DCircle CircleOther = new C2DCircle( ptOtherCen, Other.Radius ); if (CircleThis.Crosses( CircleOther , IntPts1 ) ) { for (int i = 0; i < IntPts1.Count; i++) { if ( (Line.IsOnRight( IntPts1[i] ) == ArcOnRight ) && (Other.Line.IsOnRight( IntPts1[i] ) == Other.ArcOnRight ) ) { ptOnThis.Set(IntPts1[i]); ptOnOther.Set(IntPts1[i]); return 0; } } IntPts1.Clear(); } C2DLine LineCenToOther = new C2DLine(); LineCenToOther.point = new C2DPoint(ptThisCen); LineCenToOther.vector = new C2DVector(ptThisCen, ptOtherCen); LineCenToOther.GrowFromCentre( Math.Max(Radius, Other.Radius) * 10); double dMinDist = 1.7E308; double dDist = 0; if ( Crosses(LineCenToOther, IntPts1) && Other.Crosses(LineCenToOther, IntPts2)) { for (int i = 0 ; i < IntPts1.Count; i++) { for (int j = 0 ; j < IntPts2.Count; j++) { dDist = IntPts1[i].Distance(IntPts2[j]); if (dDist < dMinDist) { ptOnThis.Set( IntPts1[i]); ptOnOther.Set( IntPts2[j]); dMinDist = dDist; } } } } C2DPoint ptOnThisTemp = new C2DPoint(); dDist = Distance(Other.GetPointFrom(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointFrom()); dMinDist = dDist; } dDist = Distance(Other.GetPointTo(), ptOnThisTemp); if (dDist < dMinDist) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(Other.GetPointTo()); dMinDist = dDist; } C2DPoint ptOnOtherTemp = new C2DPoint(); dDist = Other.Distance(GetPointFrom(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set( GetPointFrom()); ptOnOther.Set( ptOnOtherTemp); dMinDist = dDist; } dDist = Other.Distance(GetPointTo(), ptOnOtherTemp); if (dDist < dMinDist) { ptOnThis.Set( GetPointTo()); ptOnOther.Set( ptOnOtherTemp); dMinDist = dDist; } return dMinDist; }