public static Polygon Ellipse(Point center, double xRadius, double yRadius) { int precision = (int)GMath.Ceiling(GMath.Pi * GMath.Abs(xRadius + yRadius)); if (precision <= 0) { return(new Polygon(new[] { center })); } double dt = GMath.Tau / precision; double c = GMath.Cos(dt), s = GMath.Sin(dt); double x = 1, y = 0, tmp; var pts = new Point[precision]; for (int i = 0; i < precision; i++) { pts[i] = new Point(center.X + x * xRadius, center.Y + y * yRadius); tmp = x; x = c * x - s * y; y = s * tmp + c * y; } return(new Polygon(pts)); }
public static Color FromHsv(Angle h, double s, double v, int a) { var H = h.Degrees / 60; s = GMath.Median(0, s, 1); v = GMath.Median(0, v, 1); var C = v * s; var X = C * (1 - GMath.Abs(H % 2 - 1)); var m = v - C; double R, G, B; switch ((int)H) { case 0: R = C; G = X; B = 0; break; case 1: R = X; G = C; B = 0; break; case 2: R = 0; G = C; B = X; break; case 3: R = 0; G = X; B = C; break; case 4: R = X; G = 0; B = C; break; default: R = C; G = 0; B = X; break; } return(FromRgba((int)(255 * (R + m)), (int)(255 * (G + m)), (int)(255 * (B + m)), a)); }
/// <summary> /// Applies a rotation transformation to this GRaff.Matrix. /// This is equivalent to Matrix.Rotation(a) * this. /// </summary> /// <param name="a">The angle to rotate by.</param> /// <returns>This GRaff.Matrix, after the transformation.</returns> public Matrix Rotate(Angle a) { double c = GMath.Cos(a), s = GMath.Sin(a); return(new Matrix(M00 * c - M10 * s, M01 * c - M11 * s, M02 * c - M12 * s, M00 * s + M10 * c, M01 * s + M11 * c, M02 * s + M12 * c)); }
private Rectangle?_intersectionAbs(Rectangle other) { Rectangle thisAbs = this.Abs, otherAbs = other.Abs; double l = GMath.Max(thisAbs.Left, otherAbs.Left), r = GMath.Min(thisAbs.Right, otherAbs.Right), t = GMath.Max(thisAbs.Top, otherAbs.Top), b = GMath.Min(thisAbs.Bottom, otherAbs.Bottom); if (l > r || t > b) { return(null); } else { return(new Rectangle(l, t, r - l, b - t)); } }
public static Polygon Circle(Point center, double radius) { if (radius == 0) { return(new Polygon(new[] { center })); } int precision = (int)GMath.Ceiling(GMath.Tau * GMath.Abs(radius)); if (precision < 2) { precision = 2; } return(Regular(precision, radius, center)); }
public Polygon(IEnumerable <Point> pts) { _pts = pts.ToArray(); if (_pts.Length <= 2) { return; } double sum = 0; Angle a; Vector previous, next; previous = Edge(-1).Offset; next = Edge(0).Offset; a = next.Direction - previous.Direction; if (a.Degrees > 180) { Array.Reverse(_pts); previous = Edge(-1).Offset; next = Edge(0).Offset; a = next.Direction - previous.Direction; } sum += a.Degrees; for (int i = 1; i < _pts.Length; i++) { previous = next; next = Edge(i).Offset; a = next.Direction - previous.Direction; if (a.Degrees > 180) { throw new ArgumentException("The points must specify a convex polygon."); } sum += a.Degrees; } if (GMath.Abs(sum - 360) > GMath.DefaultDelta) { throw new ArgumentException($"The points must specify a convex polygon with winding number equal to 1. (Winding is {sum} degrees)"); } }
public static Polygon Regular(int degree, double radius, Point center) { Contract.Requires <ArgumentOutOfRangeException>(degree >= 2); double dt = GMath.Tau / degree; double c = GMath.Cos(dt), s = GMath.Sin(dt); double x = 0, y = -radius, tmp; Point[] pts = new Point[degree]; for (int i = 0; i < degree; i++) { pts[i] = new Point(center.X + x, center.Y + y); tmp = x; x = c * x - s * y; y = s * tmp + c * y; } return(new Polygon(pts)); }
/// <summary> /// Returns whether this line intersects the other. /// Edge cases such as if the endpoint of one line lies on the other line /// have no definite behaviour. /// </summary> public bool Intersects(Line other) { var n = LeftNormal; var h = n.Dot(other.Origin - Origin); if (h * n.Dot(other.Destination - Origin) > 0) { return(false); } else if (h * n.Dot(other.Destination - Origin) == 0) { if ((Offset.Dot(other.Origin - Origin) < 0 && Offset.Dot(other.Destination - Origin) < 0) || (Offset.Dot(other.Origin - Destination) > 0 && Offset.Dot(other.Destination - Destination) > 0)) { return(false); } else { return(true); } } var angle = other.Offset.Angle(this.Offset); if (angle.Degrees == 0 || angle.Degrees == 180) { if (h != 0) { return(false); } return(_isPointAdjacent(other.Origin) || _isPointAdjacent(other.Destination)); } var sign = n.Dot(other.Offset) > 0 ? 1 : -1; var p = other.Origin - sign * new Vector(h / GMath.Sin(angle), angle); return(_isPointAdjacent(p)); }
/// <summary> /// Finds the direction of the vector from the origin to the specified point. /// </summary> /// <param name="p">The point.</param> /// <returns>The direction of the vector from the origin to the specified point.</returns> public static Angle Direction(Point p) => GMath.Atan2(p.Y, p.X);
/// <summary> /// Finds the direction of the vector from the origin to the specified (x, y) point. /// </summary> /// <param name="x">The x-coordinate.</param> /// <param name="y">The y-coordinate.</param> /// <returns>The direction of the vector from the origin to the specified point.</returns> public static Angle Direction(double x, double y) => GMath.Atan2(y, x);
/// <summary> /// Creates a GRaff.Angle with a value specified in degrees. /// </summary> /// <param name="degrees">The angle, in degrees</param> /// <returns>the created GRaff.Angle</returns> public static Angle Deg(double degrees) => new Angle(GMath.RoundULong(GMath.Remainder((degrees * degToData), ulong.MaxValue)));
/// <summary> /// Creates a GRaff.Angle with a value specified in radians. /// </summary> /// <param name="radians">The angle, in radians.</param> /// <returns>the created GRaff.Angle</returns> public static Angle Rad(double radians) => new Angle(GMath.RoundULong(GMath.Remainder((radians * radToData), ulong.MaxValue)));
/// <summary> /// Finds the direction of the vector from the point (x1,y1) to the point (x2,y2). /// </summary> /// <param name="xFrom">The x-coordinate of the first point.</param> /// <param name="yFrom">The y-coordinate of the first point.</param> /// <param name="xTo">The x-coordinate of the second point.</param> /// <param name="yTo">The y-coordinate of the second point.</param> /// <returns>The direction of the vector from the first to the second point.</returns> public static Angle Direction(double xFrom, double yFrom, double xTo, double yTo) => GMath.Atan2(yTo - yFrom, xTo - xFrom);
/// <summary> /// Returns a hash code for this GRaff.Matrix. /// </summary> /// <returns>An integer value that specifies a hash value for this GRaff.Matrix.</returns> public override int GetHashCode() => GMath.HashCombine(M00.GetHashCode(), M01.GetHashCode(), M02.GetHashCode(), M10.GetHashCode(), M11.GetHashCode(), M12.GetHashCode());
public Vector(double magnitude, Angle direction) : this() { X = magnitude * GMath.Cos(direction); Y = magnitude * GMath.Sin(direction); }
/// <summary> /// Returns a hash code for this GRaff.Vector. /// </summary> /// <returns>An integer value that specifies a hash value for this GRaff.Vector.</returns> public override int GetHashCode() => GMath.HashCombine(X.GetHashCode(), Y.GetHashCode());
/// <summary> /// Returns a hash code for this GRaff.Rectangle. /// </summary> /// <returns>An integer value that specifies a hash value for this GRaff.Rectangle.</returns> public override int GetHashCode() => GMath.HashCombine(Left.GetHashCode(), Top.GetHashCode(), Width.GetHashCode(), Height.GetHashCode());
public Point Project(Point pt) => new Point(GMath.Median(Left, pt.X, Right), GMath.Median(Top, pt.Y, Bottom));
/// <summary> /// Returns a hash code for this GRaff.IntRectangle. /// </summary> /// <returns>An integer value that specifies a hash value for this GRaff.IntRectangle.</returns> public override int GetHashCode() => GMath.HashCombine(Left, Top, Width, Height);
/// <summary> /// Returns a hash code for this GRaff.IntVector. /// </summary> /// <returns>An integer value that specifies a hash value for this GRaff.IntVector.</returns> public override int GetHashCode() => GMath.HashCombine(X, Y);
/// <summary> /// Creates a new GRaff.Color, with the same color channels as this instance, but with the new specified opacity. /// </summary> /// <param name="opacity">The opacity of the new color. 0.0 means it is completely transparent, and 1.0 means it is completely opaque.</param> /// <returns>A new GRaff.Color with the same color as this instance, but with an alpha channel corresponding to the specified opacity.</returns> public Color Transparent(double opacity) => new Color(R, G, B, (byte)GMath.Round(255.0 * GMath.Median(0.0, opacity, 1.0)));
/// <summary> /// Returns a random number that is distributed in accordance with standard normal distribution. /// I.e. a normally distributed variable with mean 0 and standard deviation 1. /// </summary> /// <param name="rnd">The System.Random to generate the numbers.</param> /// <returns>A standard normally distributed number.</returns> public static double Gaussian(this Random rnd) => GMath.Sqrt(-2 * GMath.Log(1.0 - rnd.NextDouble()));
public Vector Component(Angle direction) => new Vector(X * GMath.Cos(direction) + Y * GMath.Sin(direction), direction);
/// <summary> /// Returns a hash code for this GRaff.Line. /// </summary> /// <returns>An integer value that specifies a hash value for this GRaff.Line.</returns> public override int GetHashCode() => GMath.HashCombine(Origin.GetHashCode(), Offset.GetHashCode());
/// <summary> /// Creates a GRaff.Matrix representing a rotation transform around the origin. /// </summary> /// <param name="a">The angle to rotate by.</param> /// <returns>A new GRaff.Matrix representing the transformation.</returns> public static Matrix Rotation(Angle a) => new Matrix(GMath.Cos(a), -GMath.Sin(a), 0, GMath.Sin(a), GMath.Cos(a), 0);
public Angle Angle(Vector other) => GMath.Acos(UnitVector.Dot(other.UnitVector));