/// <summary> /// Set to be the minimum bounding circle for the 2 points. /// </summary> /// <param name="Point1">The first point to include.</param> /// <param name="Point2">The second point to include.</param> public void SetMinimum(C2DPoint Point1, C2DPoint Point2) { C2DVector Vec = new C2DVector(Point1, Point2); Vec.Multiply( 0.5); Radius = Vec.GetLength(); _Centre.Set(Point1.GetPointTo(Vec)); }
/// <summary> /// Contructor. /// </summary> /// <param name="PtFrom">The point the arc is to go from.</param> /// <param name="Vector">The vector defining the end point.</param> /// <param name="dRadius">The corresponding circles radius.</param> /// <param name="bCentreOnRight">Whether the centre is on the right.</param> /// <param name="bArcOnRight">Whether the arc is to the right of the line.</param> public C2DArc(C2DPoint PtFrom, C2DVector Vector, double dRadius, bool bCentreOnRight, bool bArcOnRight) { Line.Set(PtFrom, Vector); Radius = dRadius; CentreOnRight = bCentreOnRight; ArcOnRight = bArcOnRight; }
/// <summary> /// Distance to a line, returns the closest point on the circle and the line. /// </summary> /// <param name="Line">Line to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on the circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the line to recieve the result.</param> public double Distance(C2DLine Line, C2DPoint ptOnThis, C2DPoint ptOnOther) { var ProjInt = new CInterval(); Project(Line, ProjInt); if (ProjInt.dMax < 0) { // This means that the circle projects entirely "below" the line so the nearest point // To this is the first point on the line and there are no interections. ptOnOther.Set(Line.point); return(Distance(Line.point, ptOnThis)); } var dLength = Line.GetLength(); if (ProjInt.dMin > dLength) { // This means that the circle projects entirely "above" the line so the nearest point // To this is the second point on the line and there are no interections. var ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set(ptClosest); return(Distance(ptClosest, ptOnThis)); } // Now find out if there's an intersection. var IntPts = new List <C2DPoint>(); if (Crosses(Line, IntPts)) { ptOnThis.Set(IntPts[0]); ptOnOther.Set(IntPts[0]); return(0); } // Now find out if the line is entirely inside if (ProjInt.dMin > 0 && ProjInt.dMax < dLength && this.Contains(Line.point)) { var d1 = Distance(Line.point, ptOnThis); var ptThisTemp = new C2DPoint(); var d2 = Distance(Line.GetPointTo(), ptThisTemp); Debug.Assert(d1 < 0 && d2 < 0); if (d2 > d1) // NOTE USE OF > AS d2 and d1 are -ve. { ptOnThis.Set(ptThisTemp); ptOnOther.Set(Line.GetPointTo()); return(d2); } else { ptOnOther.Set(Line.point); return(d1); } } // We now know the line is entirely outside. // Now find out if this is closest to a point on the line. var dCenOnLine = (ProjInt.dMax + ProjInt.dMin) / 2.0; if (dCenOnLine > 0) { if (dCenOnLine < dLength) { // The centre is projected on the line var dFactor = dCenOnLine / dLength; var vProj = new C2DVector(Line.vector); vProj.Multiply(dFactor); var ptOnLine = new C2DPoint(Line.point.GetPointTo(vProj)); ptOnOther.Set(ptOnLine); return(Distance(ptOnLine, ptOnThis)); } else { // The centre is projected above the line. var ptClosest = new C2DPoint(Line.GetPointTo()); ptOnOther.Set(ptClosest); return(Distance(ptClosest, ptOnThis)); } } else { // This means that the circle projects entirely "below" the line. ptOnOther.Set(Line.point); return(Distance(Line.point, ptOnThis)); } }
/// <summary> /// Gets the point on the line given by the factor. e.g. 0.5 = mid point. /// </summary> /// <param name="dFactorFromStart">The factor from the start.</param> public C2DPoint GetPointOn(double dFactorFromStart) { C2DVector vNew = new C2DVector(vector); vNew.Multiply( dFactorFromStart); C2DPoint Result = new C2DPoint(point.x + vNew.i, point.y + vNew.j ); return Result; }
/// <summary> /// Returns the distance from this to the point with this as a ray. /// </summary> /// <param name="TestPoint"></param> /// <param name="ptOnThis"></param> /// <returns></returns> public double DistanceAsRay(C2DPoint TestPoint, C2DPoint ptOnThis) { C2DVector vP1ToPoint = new C2DVector(point, TestPoint); // The projection is on the line double dFactorOnLine = vP1ToPoint.Dot(vector) / (vector.i * vector.i + vector.j * vector.j); ptOnThis.Set(point.x + vector.i * dFactorOnLine, point.y + vector.j * dFactorOnLine); return TestPoint.Distance(ptOnThis); }
/// <summary> /// Equality test. /// </summary> public bool VectorEqualTo( C2DVector Other) { bool biClose; bool bjClose; if (i == 0) biClose = Other.i == 0; else biClose = Math.Abs((Other.i - i) / i) < Constants.conEqualityTolerance; if (j == 0) bjClose = Other.j == 0; else bjClose = Math.Abs((Other.j - j) / j) < Constants.conEqualityTolerance; return (biClose && bjClose); }
/// <summary> /// Returns the angle to the right to another vector. /// </summary> public double AngleToRight(C2DVector Other) { double Result = Other.AngleFromNorth() - AngleFromNorth(); if (Result < 0) Result += Constants.conTWOPI; return Result; }
/// <summary> /// Moves this point by the vector given. /// </summary> /// <param name="Vector">The vector.</param> public override void Move(C2DVector Vector) { P1.Move(Vector); P2.Move(Vector); P3.Move(Vector); }
/// <summary> /// Reflects this through the point given. /// </summary> /// <param name="Other">The point to reflect this through.</param> public override void Reflect(C2DPoint Other) { // Set up a vector from this to the other C2DVector vec = new C2DVector(this, Other); // Now use the vector to find the reflection by continuing along it from the point given. this.Set( Other.GetPointTo(vec) ); }
/// <summary> /// Returns the point that the vector supplied would take this point to as a new object. /// </summary> /// <param name="v1">The vector from this to the new point.</param> public C2DPoint GetPointTo(C2DVector v1) { return(new C2DPoint(x + v1.i, y + v1.j)); }
/// <summary> /// Projects the point on the vector given returning a distance along the vector. /// </summary> /// <param name="vector">The vector to project this on.</param> /// <param name="interval">The interval to recieve the result. /// Both the min and max of the interval will be set to the result.</param> public override void Project(C2DVector vector, CInterval interval) { interval.dMax = Project(vector); interval.dMin = interval.dMax; }
/// <summary> /// Construction from a vector which can be thought of as a point (and vice versa). /// </summary> /// <param name="vector">Vector to assign to.</param> public C2DPoint(C2DVector vector) { x = vector.i; y = vector.j; }
/// <summary> /// Addition. /// </summary> public static C2DVector operator+(C2DVector V1, C2DVector V2) { var V3 = new C2DVector(V1.i + V2.i, V1.j + V2.j); return(V3); }
/// <summary> /// Distance to a circle, returns the closest point on both circles. /// </summary> /// <param name="Other">Circle to calculate the distance to.</param> /// <param name="ptOnThis">Closest point on this circle to recieve the result.</param> /// <param name="ptOnOther">Closest point on the other circle to recieve the result.</param> public double Distance(C2DCircle Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { var dCenCenDist = _Centre.Distance(Other.Centre); var dOtherRadius = Other.Radius; // C2DPoint ptThis; // C2DPoint ptOther; var dDist = dCenCenDist - Radius - dOtherRadius; if (dDist > 0) { // they do not interect and they are outside each other. var Line = new C2DLine(_Centre, Other.Centre); Line.vector.SetLength(Radius); ptOnThis.Set(Line.GetPointTo()); Line.vector.Reverse(); Line.SetPointFrom(Other.Centre); Line.vector.SetLength(Other.Radius); ptOnOther.Set(Line.GetPointTo()); } else { if ((dCenCenDist + Radius) < dOtherRadius) { // This is inside the other dDist = dCenCenDist + Radius - dOtherRadius; // -ve if inside var vec = new C2DVector(Other.Centre, Centre); vec.Multiply(Radius / dCenCenDist); // set the vector to be the length of my radius. ptOnThis.Set(_Centre.GetPointTo(vec)); vec.Multiply(dDist / Radius); // set the vector to be the distance. ptOnOther.Set(ptOnThis.GetPointTo(vec)); } else if ((dCenCenDist + dOtherRadius) < Radius) { // The other is inside this. dDist = dCenCenDist + dOtherRadius - Radius; // -ve if inside var vec = new C2DVector(_Centre, Other.Centre); vec.Multiply(dOtherRadius / dCenCenDist); // set the vector to be the length of my radius. ptOnOther.Set(Other.Centre.GetPointTo(vec)); vec.Multiply(dDist / dOtherRadius); // set the vector to be the distance. ptOnThis.Set(ptOnOther.GetPointTo(vec)); } else { // there is an intersection dDist = 0; var Ints = new List <C2DPoint>(); if (Crosses(Other, Ints)) { ptOnThis.Set(Ints[0]); ptOnOther.Set(ptOnThis); } else { Debug.Assert(false); return(0); } } } // if (ptOnThis) // *ptOnThis = ptThis; // if (ptOnOther) // *ptOnOther = ptOther; return(dDist); }
/// <summary> /// Projects the point on the line given returning a distance along the line from the start. /// </summary> /// <param name="Line">The line to project this on.</param> public double Project(C2DLine Line) { C2DVector vecthis = new C2DVector(Line.point, this ); return (vecthis.Dot(Line.vector)) / Line.vector.GetLength(); }
/// <summary> /// Returns the boolean result (e.g. union) of 2 shapes. Boolean Operation defined by /// the inside / outside flags. /// </summary> /// <param name="Other">Other polygon.</param> /// <param name="HoledPolys">Set of polygons to recieve the result.</param> /// <param name="bThisInside">Does the operation require elements of this INSIDE the other.</param> /// <param name="bOtherInside">Does the operation require elements of the other INSIDE this.</param> /// <param name="grid">The grid with the degenerate settings.</param> public void GetBoolean(C2DHoledPolyBase Other, List <C2DHoledPolyBase> HoledPolys, bool bThisInside, bool bOtherInside, CGrid grid) { if (_Rim.Lines.Count == 0 || Other.Rim.Lines.Count == 0) { return; } if (_Rim.BoundingRect.Overlaps(Other.Rim.BoundingRect)) { switch (grid.DegenerateHandling) { case CGrid.eDegenerateHandling.None: { var CompleteHoles1 = new List <C2DPolyBase>(); var CompleteHoles2 = new List <C2DPolyBase>(); var Routes1 = new C2DLineBaseSetSet(); var Routes2 = new C2DLineBaseSetSet(); GetRoutes(this, bThisInside, Other, bOtherInside, Routes1, Routes2, CompleteHoles1, CompleteHoles2, grid); Routes1.ExtractAllOf(Routes2); if (Routes1.Count > 0) { Routes1.MergeJoining(); var Polygons = new List <C2DPolyBase>(); for (var i = Routes1.Count - 1; i >= 0; i--) { C2DLineBaseSet pRoute = Routes1[i]; if (pRoute.IsClosed(true)) { Polygons.Add(new C2DPolyBase()); Polygons[Polygons.Count - 1].CreateDirect(pRoute); } else { // Debug.Assert(false); grid.LogDegenerateError(); } } var NewComPolys = new C2DHoledPolyBaseSet(); PolygonsToHoledPolygons(NewComPolys, Polygons); NewComPolys.AddKnownHoles(CompleteHoles1); NewComPolys.AddKnownHoles(CompleteHoles2); if (!bThisInside && !bOtherInside && NewComPolys.Count != 1) { // Debug.Assert(false); grid.LogDegenerateError(); } HoledPolys.AddRange(NewComPolys); NewComPolys.Clear(); } } break; case CGrid.eDegenerateHandling.RandomPerturbation: { var OtherCopy = new C2DHoledPolyBase(Other); OtherCopy.RandomPerturb(); grid.DegenerateHandling = CGrid.eDegenerateHandling.None; GetBoolean(OtherCopy, HoledPolys, bThisInside, bOtherInside, grid); grid.DegenerateHandling = CGrid.eDegenerateHandling.RandomPerturbation; } break; case CGrid.eDegenerateHandling.DynamicGrid: { var Rect = new C2DRect(); if (_Rim.BoundingRect.Overlaps(Other.Rim.BoundingRect, Rect)) { //double dOldGrid = CGrid::GetGridSize(); grid.SetToMinGridSize(Rect, false); grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGrid; GetBoolean(Other, HoledPolys, bThisInside, bOtherInside, grid); grid.DegenerateHandling = CGrid.eDegenerateHandling.DynamicGrid; } } break; case CGrid.eDegenerateHandling.PreDefinedGrid: { var P1 = new C2DHoledPolyBase(this); var P2 = new C2DHoledPolyBase(Other); P1.SnapToGrid(grid); P2.SnapToGrid(grid); var V1 = new C2DVector(P1.Rim.BoundingRect.TopLeft, P2.Rim.BoundingRect.TopLeft); var dPerturbation = grid.GridSize; // ensure it snaps back to original grid positions. if (V1.i > 0) { V1.i = dPerturbation; } else { V1.i = -dPerturbation; // move away slightly if possible } if (V1.j > 0) { V1.j = dPerturbation; } else { V1.j = -dPerturbation; // move away slightly if possible } V1.i *= 0.411923; // ensure it snaps back to original grid positions. V1.j *= 0.313131; // ensure it snaps back to original grid positions. P2.Move(V1); grid.DegenerateHandling = CGrid.eDegenerateHandling.None; P1.GetBoolean(P2, HoledPolys, bThisInside, bOtherInside, grid); for (var i = 0; i < HoledPolys.Count; i++) { HoledPolys[i].SnapToGrid(grid); } grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGrid; } break; case CGrid.eDegenerateHandling.PreDefinedGridPreSnapped: { var P2 = new C2DHoledPolyBase(Other); var V1 = new C2DVector(_Rim.BoundingRect.TopLeft, P2.Rim.BoundingRect.TopLeft); var dPerturbation = grid.GridSize; if (V1.i > 0) { V1.i = dPerturbation; } else { V1.i = -dPerturbation; // move away slightly if possible } if (V1.j > 0) { V1.j = dPerturbation; } else { V1.j = -dPerturbation; // move away slightly if possible } V1.i *= 0.411923; // ensure it snaps back to original grid positions. V1.j *= 0.313131; // ensure it snaps back to original grid positions. P2.Move(V1); grid.DegenerateHandling = CGrid.eDegenerateHandling.None; GetBoolean(P2, HoledPolys, bThisInside, bOtherInside, grid); for (var i = 0; i < HoledPolys.Count; i++) { HoledPolys[i].SnapToGrid(grid); } grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGridPreSnapped; } break; } // switch } }
/// <summary> /// True if the point projects onto the line given and returns the /// point on the line. /// </summary> /// <param name="Line"></param> public void ProjectOnRay(C2DLine Line) { C2DVector vecthis = new C2DVector(Line.point, this ); double dProj = vecthis.Dot(Line.vector); double dFactor = dProj / (Line.vector.i * Line.vector.i + Line.vector.j * Line.vector.j ); C2DVector vProj = new C2DVector(Line.vector); vProj.i *= dFactor; vProj.j *= dFactor; this.Set(Line.point.x + vProj.i, Line.point.y + vProj.j); }
/// <summary> /// Projection onto the vector. /// </summary> /// <param name="Vector">Vector to project this on.</param> /// <param name="Interval">Interval to recieve the result.</param> public void Project(C2DVector Vector, CInterval Interval) { _Rim.Project(Vector, Interval); }
/// <summary> /// Rotates this to the right about the origin provided. /// </summary> /// <param name="dAng">The angle through which to rotate.</param> /// <param name="Origin">The origin about which to rotate.</param> public override void RotateToRight(double dAng, C2DPoint Origin) { C2DVector vector = new C2DVector(Origin, this); vector.TurnRight(dAng); x = Origin.x + vector.i; y = Origin.y + vector.j; }
/// <summary> /// Subtraction. /// </summary> public static C2DVector operator-(C2DVector V1, C2DVector V2) { C2DVector V3 = new C2DVector(V1.i - V2.i, V1.j - V2.j); return(V3); }
/// <summary> /// Returns the shortest angle between 2 vectors i.e. the dot product of the norms. /// </summary> public double AngleBetween(C2DVector Other) { double dDot = this.Dot(Other); dDot /= (this.GetLength() * Other.GetLength()); return Math.Acos(dDot); }
/// <summary> /// Dot product. /// </summary> public double Dot(C2DVector Other) { return(i * Other.i + j * Other.j); }
/// <summary> /// Dot product. /// </summary> public double Dot(C2DVector Other) { return i * Other.i + j * Other.j; }
/// <summary> /// Cross product. /// </summary> public double Cross(C2DVector Other) { return(i * Other.i - j * Other.j); }
/// <summary> /// Subtraction. /// </summary> public static C2DVector operator -(C2DVector V1, C2DVector V2) { C2DVector V3 = new C2DVector(V1.i - V2.i, V1.j - V2.j); return V3; }
/// <summary> /// Returns the angle to the left to another vector. /// </summary> public double AngleToLeft(C2DVector Other) { return(Constants.conTWOPI - AngleToRight(Other)); }
/// <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 double Distance(C2DLine Other, C2DPoint ptOnThis , C2DPoint ptOnOther) { // First, project the other line onto this and if it falls entirely below it or // above it then 1. There is no intersection, 2. This is closest to one end on this line. C2DPoint ptOtherP2 = new C2DPoint(Other.GetPointTo()); C2DVector vThisP1OtherP1 = new C2DVector(point, Other.point); C2DVector vThisP1OtherP2 = new C2DVector(point, ptOtherP2); C2DPoint ptThisP2 = new C2DPoint(GetPointTo()); double dOtherP1Proj = vThisP1OtherP1.Dot(vector); double dOtherP2Proj = vThisP1OtherP2.Dot(vector); // If they are both less than 0 then the projection falls below the line. if (dOtherP1Proj <= 0 && dOtherP2Proj <= 0) { ptOnThis.Set(point); return Other.Distance(point, ptOnOther); } // Now modify the projection so it is the length along this line. double dThisLength = GetLength(); dOtherP1Proj = dOtherP1Proj / dThisLength; dOtherP2Proj = dOtherP2Proj / dThisLength; // If the projections are both above the line then the second point is closest if (dOtherP1Proj >= dThisLength && dOtherP2Proj >= dThisLength) { ptOnThis.Set(ptThisP2); return Other.Distance( ptThisP2, ptOnOther); } // This hasn't worked so try the same on the other line. C2DVector vOtherP1ThisP1 = new C2DVector (Other.point, point); C2DVector vOtherP1ThisP2 = new C2DVector(Other.point, ptThisP2); double dThisP1Proj = vOtherP1ThisP1.Dot(Other.vector); double dThisP2Proj = vOtherP1ThisP2.Dot(Other.vector); // If they are both less than 0 then the projection falls below the line. if (dThisP1Proj <= 0 && dThisP2Proj <= 0) { ptOnOther.Set( Other.point); return Distance(Other.point, ptOnThis); } // Now modify the projection so it is the length along this line. double dOtherLength = Other.GetLength(); dThisP1Proj = dThisP1Proj / dOtherLength; dThisP2Proj = dThisP2Proj / dOtherLength; // If the projections are both above the line then the second point is closest if (dThisP1Proj >= dOtherLength && dThisP2Proj >= dOtherLength) { ptOnOther.Set(ptOtherP2); return Distance( ptOtherP2, ptOnThis); } // Now test for an intersection. List<C2DPoint> IntPoint = new List<C2DPoint>(); bool B1 = true, B2 = true; if (this.Crosses(Other, IntPoint,ref B1, ref B2, false)) { ptOnOther.Set(IntPoint[0]); ptOnThis.Set(IntPoint[0]); return 0; } // Otherwise, there MUST be a point projection on one of the lines otherwise both // lines project on either side of each other which is impossible. // So find the distances to all these projections and take the minimum. double dDist = 0; double dMinDist = 0; bool bSet = false; C2DPoint ptOnThisTemp = new C2DPoint(); C2DPoint ptOnOtherTemp = new C2DPoint(); // Is the other lines first point projected on this? if (dOtherP1Proj >= 0 && dOtherP1Proj <= dThisLength) { // If so find the point on this line and get distance to it. double dFactor = dOtherP1Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor) ); dMinDist = Other.point.Distance(ptOnThisTemp); bSet = true; ptOnOther.Set(Other.point); ptOnThis.Set(ptOnThisTemp); } // Is the other lines second point projected onto this? if (dOtherP2Proj >= 0 && dOtherP2Proj <= dThisLength) { // If so find the point on this and then the distance. Is it less? double dFactor = dOtherP2Proj / dThisLength; ptOnThisTemp.Set( new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor) ); dDist = ptOtherP2.Distance(ptOnThisTemp); if (!bSet || dDist < dMinDist) { ptOnOther.Set(ptOtherP2); ptOnThis.Set(ptOnThisTemp); dMinDist = dDist; bSet = true; } } // Is the first point on this projected onto the other line? if (dThisP1Proj >= 0 && dThisP1Proj <= dOtherLength) { // If so find the point and the distance. Is it less? double dFactor = dThisP1Proj / dOtherLength; ptOnOtherTemp.Set( new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = point.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(point); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } // Is the second point on this projected onto the other line? if (dThisP2Proj >= 0 && dThisP2Proj <= dOtherLength) { // If so find the point and the distance. Is it less? double dFactor = dThisP2Proj / dOtherLength; ptOnOtherTemp.Set( new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = ptThisP2.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(ptThisP2); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } Debug.Assert( bSet ); // Now return the minimum distance return dMinDist; }
/// <summary> /// Constructor with assignment. /// </summary> /// <param name="Other">other vector.</param> public C2DVector(C2DVector Other) { i = Other.i; j = Other.j; }
/// <summary> /// Projection onto a vector. /// </summary> /// <param name="Vector">The vector to project this on.</param> /// <param name="Interval">Output. The interval.</param> public override void Project(C2DVector Vector, CInterval Interval) { double dP1 = point.Project(Vector); Interval.dMax = dP1; Interval.dMin = dP1; Interval.ExpandToInclude( GetPointTo().Project( Vector) ); }
/// <summary> /// Assignment. /// </summary> /// <param name="Other">Other vector.</param> public void Set(C2DVector Other) { i = Other.i; j = Other.j; }
/// <summary> /// This simply moves the real world rectangle. /// </summary> /// <param name="Vector">Vector to move / scroll by</param> public void ScrollReal(C2DVector Vector) { RealRect.Move(Vector); }
/// <summary> /// Projects the point on the vector given returning a distance along the vector. /// </summary> /// <param name="Vector">The vector to project this on.</param> /// <param name="Interval">The interval to recieve the result. /// Both the min and max of the interval will be set to the result.</param> public override void Project(C2DVector Vector, CInterval Interval) { Interval.dMax = Project(Vector); Interval.dMin = Interval.dMax; }
/// <summary> /// This simply moves the real world rectangle but by a scaled, screen based /// value e.g. 10 pixels to the right. The image is shown in the same place on /// the screen but the image scrolls. /// </summary> /// <param name="Vector">Vector to scroll / move by.</param> public void ScrollScreen(C2DVector Vector) { RealRect.Move(new C2DVector(Vector.i / Scale.x, Vector.j / Scale.y)); }
/// <summary> /// True if the point projects onto the line given and returns the point on the line. /// Also returns whether the line projects above or below the line if relevant. /// </summary> /// <param name="Line">The line to project this on.</param> /// <param name="ptOnLine">The point to recieve the result.</param> /// <param name="bAbove">The flag to indicate whether it projects above or below.</param> public bool ProjectsOnLine(C2DLine Line, C2DPoint ptOnLine , ref bool bAbove) { C2DVector vecthis = new C2DVector(x - Line.point.x, y - Line.point.y); double dProj = vecthis.Dot(Line.vector); if (dProj < 0) { bAbove = false; return false; } double dLength = Line.vector.GetLength(); dProj /= dLength; if (dProj > dLength) { bAbove = true; return false; } double dFactor = dProj / dLength; C2DVector vProj = new C2DVector(Line.vector); vProj.Multiply(dFactor); ptOnLine.Set(Line.point.x + vProj.i, Line.point.y + vProj.j); return true; }
/// <summary> /// Projects the point on the line given returning a distance along the line from the start. /// </summary> /// <param name="Line">The line to project this on.</param> public double Project(C2DLine Line) { C2DVector vecthis = new C2DVector(Line.point, this); return((vecthis.Dot(Line.vector)) / Line.vector.GetLength()); }
/// <summary> /// Reflects this through the line given. /// </summary> /// <param name="Line">The line to reflect this through.</param> public override void Reflect(C2DLine Line) { // First find the point along the line that this projects onto. // Make a vector from the point on the line given to this point. C2DVector vecthis = new C2DVector(Line.point, this ); // Find the length of the line given. double dLength = Line.vector.GetLength(); // Now make the projection of this point on the line. double dProj = vecthis.Dot(Line.vector); dProj /= dLength; // Find the factor along the line that the projection is. double dFactor = dProj / dLength; // Now set up a copy of the vector of the line given. C2DVector vProj = new C2DVector(Line.vector); // Multiply that by that factor calculated. vProj.Multiply(dFactor); // Use the vector to find the point on the line. C2DPoint ptOnLine = new C2DPoint(Line.point.GetPointTo(vProj) ); // Noe simply reflect this in the point. this.Reflect(ptOnLine); }
/// <summary> /// Construction from a vector which can be thought of as a point (and vice versa). /// </summary> /// <param name="Vector">Vector to assign to.</param> public C2DPoint( C2DVector Vector) { x = Vector.i; y = Vector.j; }
/// <summary> /// Returns the point that the vector supplied would take this point to as a new object. /// </summary> /// <param name="V1">The vector from this to the new point.</param> public C2DPoint GetPointTo(C2DVector V1) { return(new C2DPoint(x + V1.i, y + V1.j)); }
/// <summary> /// Projection onto the Vector. /// </summary> /// <param name="Vector">Vector to project on.</param> /// <param name="Interval">Ouput. Projection.</param> public override void Project(C2DVector Vector, CInterval Interval) { P1.Project(Vector, Interval); Interval.ExpandToInclude(P2.Project(Vector)); Interval.ExpandToInclude(P3.Project(Vector)); }
/// <summary> /// Moves this point by the vector given. /// </summary> /// <param name="vector">The vector.</param> public override void Move(C2DVector vector) { x += vector.i; y += vector.j; }
/// <summary> /// Returns the angle to the left to another vector. /// </summary> public double AngleToLeft(C2DVector Other) { return (Constants.conTWOPI - AngleToRight(Other)); }
/// <summary> /// Construction from a vector which can be thought of as a point (and vice versa). /// </summary> /// <param name="Vector">Vector to assign to.</param> public C2DPoint(C2DVector Vector) { x = Vector.i; y = Vector.j; }
/// <summary> /// Cross product. /// </summary> public double Cross(C2DVector Other) { return i * Other.j - j * Other.i; }
/// <summary> /// Projects the point on the vector given returning a distance along the vector. /// </summary> /// <param name="Vector">The vector to project this on.</param> public double Project(C2DVector Vector) { C2DVector vecthis = new C2DVector(x, y); return((vecthis.Dot(Vector)) / Vector.GetLength()); }
/// <summary> /// Moves the entity by the vector provided. /// </summary> public abstract void Move(C2DVector Vector);
/// <summary> /// Projects this onto the vector provided with the interval on the line returned. /// </summary> public abstract void Project(C2DVector Vector, CInterval Interval);
/// <summary> /// Calculates the centroid of the polygon by moving it according to each holes /// weighted centroid. /// </summary> public C2DPoint GetCentroid() { C2DPoint HoleCen = new C2DPoint(0, 0); if (_Holes.Count == 0) return Rim.GetCentroid(); C2DPoint PolyCen = Rim.GetCentroid(); double dPolyArea = Rim.GetArea(); double dHoleArea = 0; for ( int i = 0 ; i < _Holes.Count; i++) { dHoleArea += GetHole(i).GetArea(); } if (dHoleArea == 0 || dHoleArea == dPolyArea) return Rim.GetCentroid(); else { for (int i = 0 ; i < _Holes.Count; i++) { C2DPoint pt = GetHole(i).GetCentroid(); pt.Multiply(GetHole(i).GetArea() / dHoleArea); HoleCen += pt; } } C2DVector Vec = new C2DVector(HoleCen, PolyCen); Vec.Multiply( dHoleArea / (dPolyArea - dHoleArea)); PolyCen.Move(Vec); return PolyCen; }
/// <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 double Distance(C2DLine Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { // First, project the other line onto this and if it falls entirely below it or // above it then 1. There is no intersection, 2. This is closest to one end on this line. var ptOtherP2 = new C2DPoint(Other.GetPointTo()); var vThisP1OtherP1 = new C2DVector(point, Other.point); var vThisP1OtherP2 = new C2DVector(point, ptOtherP2); var ptThisP2 = new C2DPoint(GetPointTo()); var dOtherP1Proj = vThisP1OtherP1.Dot(vector); var dOtherP2Proj = vThisP1OtherP2.Dot(vector); // If they are both less than 0 then the projection falls below the line. if (dOtherP1Proj <= 0 && dOtherP2Proj <= 0) { ptOnThis.Set(point); return(Other.Distance(point, ptOnOther)); } // Now modify the projection so it is the length along this line. var dThisLength = GetLength(); dOtherP1Proj = dOtherP1Proj / dThisLength; dOtherP2Proj = dOtherP2Proj / dThisLength; // If the projections are both above the line then the second point is closest if (dOtherP1Proj >= dThisLength && dOtherP2Proj >= dThisLength) { ptOnThis.Set(ptThisP2); return(Other.Distance(ptThisP2, ptOnOther)); } // This hasn't worked so try the same on the other line. var vOtherP1ThisP1 = new C2DVector(Other.point, point); var vOtherP1ThisP2 = new C2DVector(Other.point, ptThisP2); var dThisP1Proj = vOtherP1ThisP1.Dot(Other.vector); var dThisP2Proj = vOtherP1ThisP2.Dot(Other.vector); // If they are both less than 0 then the projection falls below the line. if (dThisP1Proj <= 0 && dThisP2Proj <= 0) { ptOnOther.Set(Other.point); return(Distance(Other.point, ptOnThis)); } // Now modify the projection so it is the length along this line. var dOtherLength = Other.GetLength(); dThisP1Proj = dThisP1Proj / dOtherLength; dThisP2Proj = dThisP2Proj / dOtherLength; // If the projections are both above the line then the second point is closest if (dThisP1Proj >= dOtherLength && dThisP2Proj >= dOtherLength) { ptOnOther.Set(ptOtherP2); return(Distance(ptOtherP2, ptOnThis)); } // Now test for an intersection. var IntPoint = new List <C2DPoint>(); bool B1 = true, B2 = true; if (this.Crosses(Other, IntPoint, ref B1, ref B2, false)) { ptOnOther.Set(IntPoint[0]); ptOnThis.Set(IntPoint[0]); return(0); } // Otherwise, there MUST be a point projection on one of the lines otherwise both // lines project on either side of each other which is impossible. // So find the distances to all these projections and take the minimum. double dDist = 0; double dMinDist = 0; var bSet = false; var ptOnThisTemp = new C2DPoint(); var ptOnOtherTemp = new C2DPoint(); // Is the other lines first point projected on this? if (dOtherP1Proj >= 0 && dOtherP1Proj <= dThisLength) { // If so find the point on this line and get distance to it. var dFactor = dOtherP1Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor)); dMinDist = Other.point.Distance(ptOnThisTemp); bSet = true; ptOnOther.Set(Other.point); ptOnThis.Set(ptOnThisTemp); } // Is the other lines second point projected onto this? if (dOtherP2Proj >= 0 && dOtherP2Proj <= dThisLength) { // If so find the point on this and then the distance. Is it less? var dFactor = dOtherP2Proj / dThisLength; ptOnThisTemp.Set(new C2DPoint(point.x + vector.i * dFactor, point.y + vector.j * dFactor)); dDist = ptOtherP2.Distance(ptOnThisTemp); if (!bSet || dDist < dMinDist) { ptOnOther.Set(ptOtherP2); ptOnThis.Set(ptOnThisTemp); dMinDist = dDist; bSet = true; } } // Is the first point on this projected onto the other line? if (dThisP1Proj >= 0 && dThisP1Proj <= dOtherLength) { // If so find the point and the distance. Is it less? var dFactor = dThisP1Proj / dOtherLength; ptOnOtherTemp.Set(new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = point.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(point); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } // Is the second point on this projected onto the other line? if (dThisP2Proj >= 0 && dThisP2Proj <= dOtherLength) { // If so find the point and the distance. Is it less? var dFactor = dThisP2Proj / dOtherLength; ptOnOtherTemp.Set(new C2DPoint(Other.point.x + Other.vector.i * dFactor, Other.point.y + Other.vector.j * dFactor)); dDist = ptThisP2.Distance(ptOnOtherTemp); if (!bSet || dDist < dMinDist) { ptOnThis.Set(ptThisP2); ptOnOther.Set(ptOnOtherTemp); dMinDist = dDist; bSet = true; } } Debug.Assert(bSet); // Now return the minimum distance return(dMinDist); }
/// <summary> /// Returns the distance from this to the point. /// </summary> /// <param name="TestPoint">The test pointt.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { C2DVector vP1ToPoint = new C2DVector(point, TestPoint); double dLength = GetLength(); double dProjLength = vP1ToPoint.Dot(vector); if (dProjLength < 0) { ptOnThis.Set(point); return TestPoint.Distance(point); } else { dProjLength = dProjLength / dLength; if (dProjLength < dLength) { // The projection is on the line double dFactorOnLine = dProjLength / dLength; C2DPoint PtOnLine = new C2DPoint(point.x + vector.i * dFactorOnLine, point.y + vector.j * dFactorOnLine); ptOnThis.Set(PtOnLine); return TestPoint.Distance(PtOnLine); } else { ptOnThis .Set(GetPointTo()); return TestPoint.Distance( GetPointTo() ); } } }
/// <summary> /// Constructor. /// </summary> /// <param name="PointFrom">The point from.</param> /// <param name="VectorTo">The vector defining the second point.</param> public C2DLine(C2DPoint PointFrom, C2DVector VectorTo) { point.Set(PointFrom); vector.Set(VectorTo); }
/// <summary> /// Moves this point by the vector given. /// </summary> /// <param name="vector">The vector.</param> public override void Move(C2DVector vector) { point.Move(vector); }
/// <summary> /// Assignment. /// </summary> /// <param name="PointFrom">The point from.</param> /// <param name="VectorTo">The vector defining the second point.</param> public void Set(C2DPoint PointFrom, C2DVector VectorTo) { point.Set(PointFrom); vector.Set(VectorTo); }
/// <summary> /// Moves this point by the vector given. /// </summary> /// <param name="Vector">The vector.</param> public override void Move(C2DVector Vector) { _Centre.Move(Vector); }