/// <summary> /// Function to scale and offset a point. /// </summary> private void ScaleAndOffSet(C2DPoint pt) { pt.x -= Offset.x; pt.y -= Offset.y; pt.x *= Scale.x; pt.y *= Scale.y; }
/// <summary> /// Returns the distance from this to the other rect. 0 if there is an overlap. /// </summary> /// <param name="Other">Other rectangle.</param> public double Distance(C2DRect Other) { if (this.Overlaps(Other)) { return(0); } if (Other.GetLeft() > this.BottomRight.x) { // Other is to the right if (Other.GetBottom() > this.TopLeft.y) { // Other is to the top right C2DPoint ptTopRight = new C2DPoint(BottomRight.x, TopLeft.y); return(ptTopRight.Distance(new C2DPoint(Other.GetLeft(), Other.GetBottom()))); } else if (Other.GetTop() < this.BottomRight.y) { // Other to the bottom right return(BottomRight.Distance(Other.TopLeft)); } else { // to the right return(Other.GetLeft() - this.BottomRight.x); } } else if (Other.GetRight() < this.TopLeft.x) { // Other to the left if (Other.GetBottom() > this.TopLeft.y) { // Other is to the top left return(TopLeft.Distance(Other.BottomRight)); } else if (Other.GetTop() < this.BottomRight.y) { // Other to the bottom left C2DPoint ptBottomLeft = new C2DPoint(TopLeft.x, BottomRight.y); return(ptBottomLeft.Distance(new C2DPoint(Other.GetRight(), Other.GetTop()))); } else { //Just to the left return(this.TopLeft.x - Other.GetRight()); } } else { // There is horizontal overlap; if (Other.GetBottom() > TopLeft.y) { return(Other.GetBottom() - TopLeft.y); } else { return(BottomRight.y - Other.GetTop()); } } }
/// <summary> /// Returns the point which is closest to the origin (0,0). /// </summary> public C2DPoint GetPointClosestToOrigin() { var ptResult = new C2DPoint(); if (Math.Abs(TopLeft.x) < Math.Abs(BottomRight.x)) { // Left is closest to the origin. ptResult.x = TopLeft.x; } else { // Right is closest to the origin ptResult.x = BottomRight.x; } if (Math.Abs(TopLeft.y) < Math.Abs(BottomRight.y)) { // Top is closest to the origin. ptResult.y = TopLeft.y; } else { // Bottom is closest to the origin ptResult.y = BottomRight.y; } return(ptResult); }
/// <summary> /// True if the ray provided (infinite line starting from the first point) crosses this. /// </summary> /// <param name="Ray">The other line to test.</param> /// <param name="IntersectionPts">Output. The intersection points.</param> public bool CrossesRay(C2DLine Ray, List <C2DPoint> IntersectionPts) { C2DPoint p1 = point; C2DPoint p2 = GetPointTo(); C2DPoint p3 = Ray.point; C2DPoint p4 = Ray.GetPointTo(); double Ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x); double Ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x); double dDenominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y); if (dDenominator == 0) { return(false); } Ua = Ua / dDenominator; Ub = Ub / dDenominator; bool bResult = (Ua >= 0 && Ua <= 1) && (Ub >= 0); if (bResult) { IntersectionPts.Add(new C2DPoint(p1.x + Ua * (p2.x - p1.x), p1.y + Ua * (p2.y - p1.y))); } return(bResult); }
/// <summary> /// Returns the point which is furthest from the origin (0,0). /// </summary> public C2DPoint GetPointFurthestFromOrigin() { C2DPoint ptResult = new C2DPoint(); if (Math.Abs(TopLeft.x) > Math.Abs(BottomRight.x)) { // Left is furthest to the origin. ptResult.x = TopLeft.x; } else { // Right is furthest to the origin ptResult.x = BottomRight.x; } if (Math.Abs(TopLeft.y) > Math.Abs(BottomRight.y)) { // Top is furthest to the origin. ptResult.y = TopLeft.y; } else { // Bottom is furthest to the origin ptResult.y = BottomRight.y; } return(ptResult); }
/// <summary> /// Returns the distance between this and the other point. /// </summary> /// <param name="other">The point to return the distance to.</param> public override double Distance(C2DPoint other) { var dXd = x - other.x; var dYd = y - other.y; return(Math.Sqrt(dXd * dXd + dYd * dYd)); }
/// <summary> /// Distance from the point. /// </summary> /// <param name="TestPoint">Point to find the distance to.</param> public double Distance(C2DPoint TestPoint) { var dResult = _Rim.Distance(TestPoint); var bInside = dResult < 0; dResult = Math.Abs(dResult); for (var i = 0; i < _Holes.Count; i++) { var dDist = _Holes[i].Distance(TestPoint); if (dDist < 0) { bInside = false; } if (Math.Abs(dDist) < dResult) { dResult = Math.Abs(dDist); } } if (bInside) { return(dResult); } else { return(-dResult); } }
/// <summary> /// Set to be the minimum bounding circle for the 3 points. /// </summary> /// <param name="Point1">The first point to include.</param> /// <param name="Point2">The second point to include.</param> /// <param name="Point3">The third point to include.</param> public void SetMinimum(C2DPoint Point1, C2DPoint Point2, C2DPoint Point3) { double dDist12 = Point1.Distance(Point2); double dDist23 = Point2.Distance(Point3); double dDist31 = Point3.Distance(Point1); if (dDist12 >= dDist23 && dDist12 >= dDist31) { SetMinimum(Point1, Point2); if (this.Contains(Point3)) { return; } } else if (dDist23 >= dDist31) { SetMinimum(Point2, Point3); if (this.Contains(Point1)) { return; } } else { SetMinimum(Point3, Point1); if (this.Contains(Point2)) { return; } } // If here, the simple minimum of any 2 doesn't incorporate the other 1 so the // minimum is the circumscribed circle. SetCircumscribed(Point1, Point2, Point3); }
/// <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) { var vecthis = new C2DVector(x - line.point.x, y - line.point.y); var dProj = vecthis.Dot(line.vector); if (dProj < 0) { bAbove = false; return(false); } var dLength = line.vector.GetLength(); dProj /= dLength; if (dProj > dLength) { bAbove = true; return(false); } var dFactor = dProj / dLength; var vProj = new C2DVector(line.vector); vProj.Multiply(dFactor); ptOnLine.Set(line.point.x + vProj.i, line.point.y + vProj.j); return(true); }
// Update is called once per frame void Update() { if (guiController.IsMenu ()) return; var screenPos = Camera.main.ScreenToWorldPoint (inputController.GetPosition ()); var worldPos = new Vector3 (screenPos.x, screenPos.y, -2); if (inputController.IsEventStart ()) { if (_stone == null) { _stone = GameObjectManager.CreateStone (logicController.toPlay, worldPos); } } else { if (_stone != null){ _stone.transform.localPosition = worldPos; _stone.GetComponent<StoneView>().Legal = logicController.HasPlace(new C2DPoint(worldPos.x, worldPos.y)); if (inputController.IsEventEnd ()) { var point = new C2DPoint(_stone.transform.position.x, _stone.transform.position.y); if (logicController.addStone(point)) { networkController.SendPoint(point); _stone.transform.localPosition = new Vector3(worldPos.x, worldPos.y, 0); _stone.GetComponent<StoneView>().HideBackground(); _stone = null; } else { GameObject.Destroy(_stone); } } } } }
/// <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) { var vP1ToPoint = new C2DVector(point, TestPoint); var dLength = GetLength(); var 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 var dFactorOnLine = dProjLength / dLength; var 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> /// 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> /// Set to be the minimum bounding circle for the 3 points. /// </summary> /// <param name="Point1">The first point to include.</param> /// <param name="Point2">The second point to include.</param> /// <param name="Point3">The third point to include.</param> public void SetMinimum(C2DPoint Point1, C2DPoint Point2, C2DPoint Point3) { double dDist12 = Point1.Distance(Point2); double dDist23 = Point2.Distance(Point3); double dDist31 = Point3.Distance(Point1); if (dDist12 >= dDist23 && dDist12 >= dDist31) { SetMinimum(Point1, Point2); if (this.Contains(Point3)) return; } else if (dDist23 >= dDist31) { SetMinimum(Point2, Point3); if (this.Contains(Point1)) return; } else { SetMinimum(Point3, Point1); if (this.Contains(Point2)) return; } // If here, the simple minimum of any 2 doesn't incorporate the other 1 so the // minimum is the circumscribed circle. SetCircumscribed(Point1, Point2, Point3); }
/// <summary> /// Returns the corresponding circle's centre. /// </summary> public C2DPoint GetCircleCentre() { if (!IsValid()) { return(new C2DPoint(0, 0)); } C2DPoint MidPoint = new C2DPoint(Line.GetMidPoint()); double dMinToStart = MidPoint.Distance(Line.point); double dMidToCentre = Math.Sqrt(Radius * Radius - dMinToStart * dMinToStart); C2DVector MidToCentre = new C2DVector(Line.vector); if (CentreOnRight) { MidToCentre.TurnRight(); } else { MidToCentre.TurnLeft(); } MidToCentre.SetLength(dMidToCentre); return(MidPoint.GetPointTo(MidToCentre)); }
/// <summary> /// Distance between this and the test point. /// </summary> /// <param name="TestPoint">The test point.</param> /// <param name="ptOnThis">The closest point on this to the given point as a returned value.</param> public override double Distance(C2DPoint TestPoint, C2DPoint ptOnThis) { C2DPoint ptCen = new C2DPoint(GetCircleCentre()); C2DCircle Circle = new C2DCircle(ptCen, Radius); C2DPoint ptOnCircle = new C2DPoint(); double dCircleDist = Circle.Distance(TestPoint, ptOnCircle); if (ArcOnRight ^ Line.IsOnRight(ptOnCircle)) { // The closest point on the circle isn't on the curve double d1 = TestPoint.Distance(Line.point); double d2 = TestPoint.Distance(Line.GetPointTo()); if (d1 < d2) { ptOnThis.Set(Line.point); return(d1); } else { ptOnThis.Set(Line.GetPointTo()); return(d2); } } else { // The closest point on the circle IS on the curve ptOnThis.Set(ptOnCircle); return(Math.Abs(dCircleDist)); } }
/// <summary> /// Gets the point on the curve determined by the factor as a new object. /// </summary> public C2DPoint GetPointOn(double dFactorFromStart) { Debug.Assert(IsValid(), "Invalid arc defined, function failure."); // make 2 lines from the centre to the ends of the line C2DPoint ptCentre = new C2DPoint(GetCircleCentre()); C2DLine CenToStart = new C2DLine(ptCentre, Line.point); C2DLine CenToEnd = new C2DLine(ptCentre, Line.GetPointTo()); if (!ArcOnRight) // clockwise { // Find the angle from one to the other and muliply it by the factor // before turning the line's vector by the result. double dAngleToRight = CenToStart.vector.AngleToRight(CenToEnd.vector); double dNewAngle = dAngleToRight * dFactorFromStart; CenToStart.vector.TurnRight(dNewAngle); return(CenToStart.GetPointTo()); } else // anticlockwise { double dAngleToLeft = CenToStart.vector.AngleToLeft(CenToEnd.vector); double dNewAngle = dAngleToLeft * dFactorFromStart; CenToStart.vector.TurnLeft(dNewAngle); return(CenToStart.GetPointTo()); } }
/// <summary> /// Returns the distance between this and the other point. /// </summary> /// <param name="Other">The point to return the distance to.</param> public override double Distance(C2DPoint Other) { double dXD = x - Other.x; double dYD = y - Other.y; return(Math.Sqrt(dXD * dXD + dYD * dYD)); }
/// <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> /// Equality test which really tests for point proximity. /// <seealso cref="Constants.conEqualityTolerance"/> /// </summary> /// <param name="Other">The other point.</param> public bool PointEqualTo(C2DPoint Other) { bool bxClose; bool byClose; if (x == 0) { bxClose = Other.x == 0; } else { bxClose = Math.Abs((Other.x - x) / x) < Constants.conEqualityTolerance; } if (!bxClose) { return(false); // Get out early if we can. } if (y == 0) { byClose = Other.y == 0; } else { byClose = Math.Abs((Other.y - y) / y) < Constants.conEqualityTolerance; } return(byClose); // We know x is close. }
/// <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> /// Draws a rectangle filled. /// </summary> public void DrawFilled(C2DRect Rect, Graphics graphics, Brush brush) { C2DPoint pt1 = new C2DPoint(Rect.TopLeft); C2DPoint pt2 = new C2DPoint(Rect.BottomRight); this.ScaleAndOffSet(pt1); this.ScaleAndOffSet(pt2); int TLx = (int)pt1.x; if (Scale.x < 0) { TLx = (int)pt2.x; } int TLy = (int)pt2.y; if (Scale.x < 0) { TLy = (int)pt1.y; } graphics.FillRectangle(brush, TLx, TLy, (int)Math.Abs(pt1.x - pt2.x), (int)Math.Abs(pt1.y - pt2.y)); }
/// <summary> /// Grow the height it from its centre. /// </summary> /// <param name="dFactor">Factor to grow by.</param> public void GrowHeight(double dFactor) { C2DPoint ptCentre = new C2DPoint(GetCentre()); BottomRight.y = (BottomRight.y - ptCentre.y) * dFactor + ptCentre.y; TopLeft.y = (TopLeft.y - ptCentre.y) * dFactor + ptCentre.y; }
/// <summary> /// Grows the width from its centre. /// </summary> /// <param name="dFactor">Factor to grow by.</param> public void GrowWidth(double dFactor) { C2DPoint ptCentre = new C2DPoint(GetCentre()); BottomRight.x = (BottomRight.x - ptCentre.x) * dFactor + ptCentre.x; TopLeft.x = (TopLeft.x - ptCentre.x) * dFactor + ptCentre.x; }
/// <summary> /// True if the point is in the shape. /// </summary> /// <param name="pt">The point to test set.</param> public bool Contains(C2DPoint pt) { if (!BoundingRect.Contains(pt)) { return(false); } var IntersectedPts = new C2DPointSet(); var Ray = new C2DLine(pt, new C2DVector(BoundingRect.Width(), 0.000001)); // Make sure to leave if (!this.Crosses(Ray, IntersectedPts)) { return(false); } else { IntersectedPts.SortByDistance(Ray.point); if (IntersectedPts[0].PointEqualTo(pt)) { // For integers, the pt can start On a line, meaning it's INSIDE, but the ray could cross again // so just return true. Because the equality test is really a test for proximity, this leads to the // possibility that a point could lie just outside the shape but be considered to be inside. This would // only be a problem with very small shapes that are a very long way from the origin. E.g. a 1m2 object // 1 million metres from the origin and a point 0.1mm away from the edge would give rise to a relative // difference of 0.0001 / 1000000 = 0.000000001 which would just be consider to be inside. return(true); } else { // Return true if the ray return((IntersectedPts.Count & (int)1) > 0); } } }
/// <summary> /// True if the point is in the shape. /// </summary> /// <param name="pt">The point to test set.</param> public bool Contains(C2DPoint pt) { if (!BoundingRect.Contains(pt)) return false; C2DPointSet IntersectedPts = new C2DPointSet (); C2DLine Ray = new C2DLine(pt, new C2DVector(BoundingRect.Width(), 0.000001)); // Make sure to leave if (!this.Crosses(Ray, IntersectedPts)) return false; else { IntersectedPts.SortByDistance(Ray.point); if ( IntersectedPts[0].PointEqualTo(pt)) { // For integers, the pt can start On a line, meaning it's INSIDE, but the ray could cross again // so just return true. Because the equality test is really a test for proximity, this leads to the // possibility that a point could lie just outside the shape but be considered to be inside. This would // only be a problem with very small shapes that are a very long way from the origin. E.g. a 1m2 object // 1 million metres from the origin and a point 0.1mm away from the edge would give rise to a relative // difference of 0.0001 / 1000000 = 0.000000001 which would just be consider to be inside. return true; } else { // Return true if the ray return (IntersectedPts.Count & (int)1) > 0; } } }
/// <summary> /// Distance to the line. /// </summary> /// <param name="Line">The line to test.</param> public double Distance(C2DLineBase Line) { if (Lines.Count == 0) { return(0); } var pt1 = new C2DPoint(); var pt2 = new C2DPoint(); double dMin = Lines[0].Distance(Line, pt1, pt2); double dDist; for (var i = 1; i < Lines.Count; i++) { dDist = Lines[i].Distance(Line, pt1, pt2); if (dDist == 0) { return(0); } if (dDist < dMin) { dMin = dDist; } } if (Contains(Line.GetPointFrom())) { return(-dMin); } else { return(dMin); } }
/// <summary> /// Distance of the point from the shape. Returns -ve if inside. /// </summary> /// <param name="pt">The point to test.</param> public override double Distance(C2DPoint pt) { if (Lines.Count == 0) { return(0); } double dResult = Lines[0].Distance(pt); for (var i = 1; i < Lines.Count; i++) { double dDist = Lines[i].Distance(pt); if (dDist < dResult) { dResult = dDist; } } if (Contains(pt)) { return(-dResult); } else { return(dResult); } }
/// <summary> /// Static version of InCentre function. /// </summary> public static C2DPoint GetInCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3) { // Set up a line to bisect the lines from 1 to 2 and 1 to 3 var Line1 = new C2DLine(pt1, pt2); var Line2 = new C2DLine(pt1, pt3); Line1.SetLength(Line2.GetLength()); var Line12Bisect = new C2DLine(pt1, pt3.GetMidPoint(Line1.GetPointTo())); // Set up a line to bisect the lines from 2 to 1 and 2 to 3 var Line3 = new C2DLine(pt2, pt1); var Line4 = new C2DLine(pt2, pt3); Line3.SetLength(Line4.GetLength()); var Line34Bisect = new C2DLine(pt2, pt3.GetMidPoint(Line3.GetPointTo())); // Now intersect the 2 lines and find the point. var Int = new List <C2DPoint>(); // Add the intersection even if there isn't one (i.e. infinite lines) bool B1 = true, B2 = true; Line12Bisect.Crosses(Line34Bisect, Int, ref B1, ref B2, true); Debug.Assert(Int.Count == 1); return(Int[0]); }
/// <summary> /// Static version of circumcentre function. /// </summary> public static C2DPoint GetCircumCentre(C2DPoint pt1, C2DPoint pt2, C2DPoint pt3) { var Line12 = new C2DLine(pt1, pt2); var Line23 = new C2DLine(pt2, pt3); // Move the lines to start from the midpoint on them Line12.point.Set(Line12.GetMidPoint()); Line23.point.Set(Line23.GetMidPoint()); // Turn them right (left would work as well) Line12.vector.TurnRight(); Line23.vector.TurnRight(); // Find the intersection between them taking the intersect point even if they don't // intersect directly (i.e. where they would intersect because we may have turned them // the wrong way). var IntPt = new List <C2DPoint>(); bool B1 = true, B2 = true; Line12.Crosses(Line23, IntPt, ref B1, ref B2, true); var ptResult = new C2DPoint(0, 0); if (IntPt.Count == 1) { ptResult = IntPt[0]; } else { // co-linear so fail. Debug.Assert(false, "Colinnear triangle. Cannot calculate Circum Centre"); } return(ptResult); }
/// <summary> /// Scales the rectangle accordingly. /// </summary> public void Scale(C2DPoint ptScale) { TopLeft.x = TopLeft.x * ptScale.x; TopLeft.y = TopLeft.y * ptScale.y; BottomRight.x = BottomRight.x * ptScale.x; BottomRight.y = BottomRight.y * ptScale.y; }
/// <summary> /// Point reflection. /// </summary> /// <param name="Line">The line through which to reflect this.</param> public override void Reflect(C2DLine Line) { var pointTo = new C2DPoint(GetPointTo()); point.Reflect(Line); pointTo.Reflect(Line); SetPointTo(pointTo); }
/// <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> /// 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> /// Assignment. /// </summary> /// <param name="PtFrom">The point the arc is to go from.</param> /// <param name="PtTo">The point the arc is to go to.</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 void Set(C2DPoint PtFrom, C2DPoint PtTo, double dRadius, bool bCentreOnRight, bool bArcOnRight) { Line.Set(PtFrom, PtTo); Radius = dRadius; CentreOnRight = bCentreOnRight; ArcOnRight = bArcOnRight; }
void afterMove(C2DPoint pos, Constants.StoneColor color) { forbiddenShapes.Add (makeCircle(pos,Constants.stoneSize)); if (color == Constants.StoneColor.Black) { toPlay = Constants.StoneColor.White; } else { toPlay = Constants.StoneColor.Black; } Debug.Log (blackShape.Count); Debug.Log (whiteShape.Count); }
public bool addStone(C2DPoint pos) { Constants.StoneColor color = toPlay; //TODO: copy here List<C2DHoledPolyArc> _blackShape = blackShape; List<C2DHoledPolyArc> _whiteShape = whiteShape; if (HasPlace (pos) && isLegal(pos, color, _blackShape, _whiteShape)) { makeMove (pos, color, blackShape, whiteShape); afterMove (pos, color); return true; } return false; }
C2DHoledPolyArc makeCircle(C2DPoint pos, float radius) { C2DPolyArc shape = new C2DPolyArc (); shape.SetStartPoint (new C2DPoint(pos.x+radius,pos.y)); for (int i = 0; i < 16; i++) { shape.LineTo(new C2DPoint (pos.x + Mathf.Cos(Mathf.PI*2*i/16)*radius, pos.y+ Mathf.Sin(Mathf.PI*2*i/16)*radius), radius, false, true); } shape.Close (radius, false, true); C2DHoledPolyArc result = new C2DHoledPolyArc (); result.Rim = shape; return result; }
/// <summary> /// Adds a point which is a striaght line from the previous. /// </summary> /// <param name="Point">The point to go to.</param> public void LineTo(C2DPoint Point) { if (Lines.Count == 0) return; C2DLine pLine = new C2DLine( Lines[Lines.Count - 1].GetPointTo(), Point ); 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> /// 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); } }
void makeMove(C2DPoint pos, Constants.StoneColor color, List<C2DHoledPolyArc> blackShape, List<C2DHoledPolyArc> whiteShape) { C2DHoledPolyArc stoneShape = makeCircle (pos, 1); List<C2DHoledPolyArc> ownShape; if (color == Constants.StoneColor.Black) { ownShape = blackShape; } else { ownShape = whiteShape; } List<C2DHoledPolyArc> shapesToMerge = new List<C2DHoledPolyArc> (); foreach (C2DHoledPolyArc poly in ownShape) { if (poly.Overlaps(stoneShape)) { shapesToMerge.Add(poly); } } merge(stoneShape, shapesToMerge, ownShape); }
/// <summary> /// Returns the distance from this to the point. /// </summary> /// <param name="TestPoint">The test point.</param> public override double Distance(C2DPoint TestPoint) { C2DPoint P1 = new C2DPoint(); return Distance(TestPoint, P1); }
/// <summary> /// True if part of this line is above the other. Returns the point /// on this and on the other. /// </summary> /// <param name="Other"></param> /// <param name="dVerticalDistance"></param> /// <param name="ptOnThis"></param> /// <param name="ptOnOther"></param> /// <returns></returns> public bool OverlapsAbove(C2DLine Other, ref double dVerticalDistance, C2DPoint ptOnThis, C2DPoint ptOnOther) { // Get the 2 points for both lines C2DPoint OtherTo = new C2DPoint(Other.point.x + Other.vector.i, Other.point.y + Other.vector.j); C2DPoint ThisTo = new C2DPoint(point.x + vector.i, point.y + vector.j); // Make an interval for both in the x plane CInterval iThis = new CInterval( point.x, point.x); iThis.ExpandToInclude( ThisTo.x ); CInterval iOther = new CInterval( Other.point.x, Other.point.x); iOther.ExpandToInclude( OtherTo.x ); // This is an interval for the overlap between the 2 CInterval iOverlap = new CInterval(); // If there is an overlap... if (iThis.Overlaps(iOther, iOverlap)) { double dThisYMin; double dThisYMax; double dOtherYMin; double dOtherYMax; // If the line is vertical then y at the x min / max can be set to the ends of the line. if (vector.i == 0) { dThisYMin = point.y; dThisYMax = ThisTo.y; } else // otherwise, caluclate the y values at the interval ends { dThisYMin = GetY(iOverlap.dMin); dThisYMax = GetY(iOverlap.dMax); } // Now do the same for the other line if (Other.vector.i == 0) { dOtherYMin = Other.point.y; dOtherYMax = OtherTo.y; } else { dOtherYMin = Other.GetY(iOverlap.dMin); dOtherYMax = Other.GetY(iOverlap.dMax); } // Now find the distance between the 2 at the ends double dDistMin = dThisYMin - dOtherYMin; double dDistMax = dThisYMax - dOtherYMax; // If they are both > 0 then no intersection if ( (dDistMin > 0) && (dDistMax > 0)) { dDistMin = Math.Abs( dDistMin); dDistMax = Math.Abs(dDistMax); // find which one is smallest if ( dDistMin > dDistMax) { dVerticalDistance = dDistMax; // distance at the max is smallest ptOnThis.x = iOverlap.dMax; ptOnThis.y = dThisYMax; ptOnOther.x = iOverlap.dMax; ptOnOther.y = dOtherYMax; } else { dVerticalDistance = dDistMin; // distance at the min is smallest ptOnThis.x = iOverlap.dMin; ptOnThis.y = dThisYMin; ptOnOther.x = iOverlap.dMin; ptOnOther.y = dOtherYMin; } return true; } else if ( (dDistMin < 0) && (dDistMax < 0)) // This is below. { return false; } else { // find the intersection. dVerticalDistance = 0; C2DPointSet pts = new C2DPointSet(); if(this.Crosses(Other, pts)) { ptOnThis = pts[0]; ptOnOther = ptOnThis; } else { Debug.Assert(false); } } return true; } else { return false; } }
/// <summary> /// Point reflection. /// </summary> /// <param name="Line">The line through which to reflect this.</param> public override void Reflect(C2DLine Line) { C2DPoint pointTo = new C2DPoint(GetPointTo()); point.Reflect(Line); pointTo.Reflect(Line); SetPointTo(pointTo); }
/// <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) { point.RotateToRight(dAng, Origin); vector.TurnRight(dAng); }
/// <summary> /// Gets the mid point on the line. /// </summary> public C2DPoint GetMidPoint() { C2DPoint Result = new C2DPoint(point.x + vector.i / 2, point.y + vector.j / 2); return Result; }
/// <summary> /// Constructor. /// </summary> /// <param name="PointFrom">The point from.</param> /// <param name="PointTo">The point to.</param> public C2DLine(C2DPoint PointFrom, C2DPoint PointTo) { point.Set(PointFrom); vector.Set(PointFrom, PointTo); }
/// <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> /// 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> /// Transform by a user defined transformation. e.g. a projection. /// </summary> public override void InverseTransform(CTransformation pProject) { C2DPoint pt2 = new C2DPoint(point.x + vector.i, point.y + vector.j); pProject.InverseTransform(point.x, point.y); pProject.InverseTransform(pt2.x, pt2.y); vector.i = pt2.x - point.x; vector.j = pt2.y - point.y; }
/// <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> /// Sets the point that this is going to. /// </summary> /// <param name="PointTo">The point to go to.</param> public void SetPointTo(C2DPoint PointTo) { vector.Set(PointTo - point); }
/// <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> /// Sets the point that this is going to. The second point is unchanged. /// </summary> /// <param name="PointFrom">The point to go from.</param> public void SetPointFrom( C2DPoint PointFrom) { // Get point to. C2DPoint PointTo = new C2DPoint(point.x + vector.i, point.y + vector.j); // Set the point from point.Set(PointFrom); // Rest the point to. vector.Set(PointTo - point); }
/// <summary> /// Grows the line about the origin. /// </summary> /// <param name="dFactor">The factor to grow by.</param> /// <param name="Origin">The origin about which to grow.</param> public override void Grow(double dFactor, C2DPoint Origin) { C2DPoint pointTo = new C2DPoint(GetPointTo()); point.Grow(dFactor, Origin); pointTo.Grow(dFactor, Origin); SetPointTo(pointTo); }
/// <summary> /// True if the point is to the right of the line. /// </summary> /// <param name="OtherPoint">The new point to test.</param> public bool IsOnRight(C2DPoint OtherPoint) { return ( C2DTriangle.GetAreaSigned( point, GetPointTo(), OtherPoint) < 0); }
/// <summary> /// Assignment. /// </summary> /// <param name="PointFrom">The point from.</param> /// <param name="PointTo">The point to.</param> public void Set(C2DPoint PointFrom, C2DPoint PointTo) { point.Set(PointFrom); vector.Set(PointFrom, PointTo); }
/// <summary> /// Returns the second point as a new object. /// </summary> public override C2DPoint GetPointTo() { C2DPoint PointTo = new C2DPoint(point.x + vector.i, point.y + vector.j); return PointTo; }
/// <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> /// Function to join the 2 lines at the point where they do / would intersect. If they do then /// the lines are clipped to remove the smallest part of the line. Returns false if they /// cannot be joined. /// </summary> /// <param name="Other">The other line</param> public bool Join(C2DLine Other) { C2DPoint p1 = point; C2DPoint p2 = GetPointTo(); C2DPoint p3 = Other.point; C2DPoint p4 = Other.GetPointTo(); double Ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x); double Ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x); double dDenominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y); if (dDenominator == 0) return false; Ua = Ua / dDenominator; Ub = Ub / dDenominator; C2DPoint IntPt = new C2DPoint(p1.x + Ua * (p2.x - p1.x), p1.y + Ua * (p2.y - p1.y)); if ( Ua >=0.5) this.SetPointTo( IntPt ); else this.SetPointFrom( IntPt ); if ( Ub >=0.5) Other.SetPointTo( IntPt ); else Other.SetPointFrom( IntPt ); return true; }