# Conflicts:
#	samples/DrawShapesWithImageSharp/DrawShapesWithImageSharp.csproj
#	samples/DrawShapesWithImageSharp/ImageSharpLogo.cs
#	samples/DrawShapesWithImageSharp/Program.cs
This commit is contained in:
Scott Williams 2017-05-30 21:12:03 +01:00
Родитель 6939a20cd7 117602d579
Коммит 8d8e327db2
40 изменённых файлов: 830 добавлений и 375 удалений

Просмотреть файл

@ -102,9 +102,9 @@ namespace SixLabors.Shapes
return this;
}
var points = new Vector2[this.controlPoints.Length];
var i = 0;
foreach (var p in this.controlPoints)
Vector2[] points = new Vector2[this.controlPoints.Length];
int i = 0;
foreach (Vector2 p in this.controlPoints)
{
points[i++] = Vector2.Transform(p, matrix);
}

Просмотреть файл

@ -25,11 +25,11 @@ namespace SixLabors.Shapes
/// <returns>Returns a new shape with the holes cliped out out the shape.</returns>
public static IPath Clip(this IPath shape, IEnumerable<IPath> holes)
{
var clipper = new PolygonClipper.Clipper();
Clipper clipper = new PolygonClipper.Clipper();
clipper.AddPath(shape, ClippingType.Subject);
clipper.AddPaths(holes, ClippingType.Clip);
var result = clipper.GenerateClippedShapes();
System.Collections.Immutable.ImmutableArray<IPath> result = clipper.GenerateClippedShapes();
return new ComplexPolygon(result);
}

Просмотреть файл

@ -34,14 +34,28 @@ namespace SixLabors.Shapes
/// </summary>
/// <param name="paths">The paths.</param>
public ComplexPolygon(ImmutableArray<IPath> paths)
{
if (paths.Length == 1)
{
this.Length = paths[0].Length;
this.Bounds = paths[0].Bounds;
this.PathType = paths[0].PathType;
this.MaxIntersections = paths[0].MaxIntersections;
}
else
{
float minX = float.MaxValue;
float maxX = float.MinValue;
float minY = float.MaxValue;
float maxY = float.MinValue;
float length = 0;
int intersections = 0;
foreach (IPath s in paths)
{
length += s.Length;
if (s.Bounds.Left < minX)
{
minX = s.Bounds.Left;
@ -62,23 +76,23 @@ namespace SixLabors.Shapes
maxY = s.Bounds.Bottom;
}
this.MaxIntersections += s.MaxIntersections;
intersections += s.MaxIntersections;
}
if (paths.Length == 1)
{
this.PathType = paths[0].PathType;
}
else
{
this.MaxIntersections = intersections;
this.Length = length;
this.Bounds = new Rectangle(minX, minY, maxX - minX, maxY - minY);
this.PathType = PathTypes.Mixed;
}
this.Paths = paths;
this.Bounds = new Rectangle(minX, minY, maxX - minX, maxY - minY);
}
/// <summary>
/// Gets the length of the path.
/// </summary>
public float Length { get; }
/// <summary>
/// Gets a value indicating whether this instance is closed, open or a composite path with a mixture of open and closed figures.
/// </summary>
@ -123,11 +137,11 @@ namespace SixLabors.Shapes
public PointInfo Distance(Vector2 point)
{
float dist = float.MaxValue;
var pointInfo = default(PointInfo);
PointInfo pointInfo = default(PointInfo);
bool inside = false;
foreach (IPath shape in this.Paths)
{
var d = shape.Distance(point);
PointInfo d = shape.Distance(point);
if (d.DistanceFromPath <= 0)
{
@ -189,7 +203,7 @@ namespace SixLabors.Shapes
public bool Contains(Vector2 point)
{
bool inside = false;
foreach (var shape in this.Paths)
foreach (IPath shape in this.Paths)
{
if (shape.Contains(point))
{
@ -215,9 +229,9 @@ namespace SixLabors.Shapes
return this;
}
var shapes = new IPath[this.Paths.Length];
var i = 0;
foreach (var s in this.Paths)
IPath[] shapes = new IPath[this.Paths.Length];
int i = 0;
foreach (IPath s in this.Paths)
{
shapes[i++] = s.Transform(matrix);
}
@ -233,8 +247,8 @@ namespace SixLabors.Shapes
/// </returns>
public ImmutableArray<ISimplePath> Flatten()
{
var paths = new List<ISimplePath>();
foreach (var path in this.Paths)
List<ISimplePath> paths = new List<ISimplePath>();
foreach (IPath path in this.Paths)
{
paths.AddRange(path.Flatten());
}
@ -257,7 +271,7 @@ namespace SixLabors.Shapes
else
{
IPath[] paths = new IPath[this.Paths.Length];
for (var i = 0; i < this.Paths.Length; i++)
for (int i = 0; i < this.Paths.Length; i++)
{
paths[i] = this.Paths[i].AsClosedPath();
}
@ -265,5 +279,32 @@ namespace SixLabors.Shapes
return new ComplexPolygon(paths);
}
}
/// <summary>
/// Calculates the the point a certain distance a path.
/// </summary>
/// <param name="distanceAlongPath">The distance along the path to find details of.</param>
/// <returns>
/// Returns details about a point along a path.
/// </returns>
public SegmentInfo PointAlongPath(float distanceAlongPath)
{
distanceAlongPath = distanceAlongPath % this.Length;
foreach(IPath p in this.Paths)
{
if(p.Length >= distanceAlongPath)
{
return p.PointAlongPath(distanceAlongPath);
}
else
{
//reduce it before trying the next path
distanceAlongPath -= p.Length;
}
}
throw new InvalidOperationException("Should not be possible to reach this line");
}
}
}

Просмотреть файл

@ -94,10 +94,13 @@ namespace SixLabors.Shapes
/// </summary>
int IPath.MaxIntersections => this.innerPath.PointCount;
/// <inheritdoc />
public float Length => this.innerPath.Length;
/// <inheritdoc />
public PointInfo Distance(Vector2 point)
{
var dist = this.innerPath.DistanceFromPath(point);
PointInfo dist = this.innerPath.DistanceFromPath(point);
bool isInside = this.innerPath.PointInPolygon(point);
if (isInside)
{
@ -189,17 +192,17 @@ namespace SixLabors.Shapes
const float kappa = 0.5522848f;
var sizeVector = size.ToVector2() / 2;
Vector2 sizeVector = size.ToVector2() / 2;
var rootLocation = location - sizeVector;
Vector2 rootLocation = location - sizeVector;
var pointO = sizeVector * kappa;
var pointE = location + sizeVector;
var pointM = location;
var pointMminusO = pointM - pointO;
var pointMplusO = pointM + pointO;
Vector2 pointO = sizeVector * kappa;
Vector2 pointE = location + sizeVector;
Vector2 pointM = location;
Vector2 pointMminusO = pointM - pointO;
Vector2 pointMplusO = pointM + pointO;
var points = new Vector2[]
Vector2[] points = new Vector2[]
{
new Vector2(rootLocation.X, pointM.Y),
@ -221,5 +224,12 @@ namespace SixLabors.Shapes
};
return new BezierLineSegment(points);
}
/// <inheritdoc />
public SegmentInfo PointAlongPath(float distanceAlongPath)
{
// TODO switch this out to a calculated algorithum
return this.innerPath.PointAlongPath(distanceAlongPath);
}
}
}

Просмотреть файл

@ -29,14 +29,14 @@ namespace SixLabors.Shapes
return source1;
}
var target = new T[source1.Length + source2.Length];
T[] target = new T[source1.Length + source2.Length];
for (var i = 0; i < source1.Length; i++)
for (int i = 0; i < source1.Length; i++)
{
target[i] = source1[i];
}
for (var i = 0; i < source2.Length; i++)
for (int i = 0; i < source2.Length; i++)
{
target[i + source1.Length] = source2[i];
}

Просмотреть файл

@ -27,7 +27,7 @@ namespace SixLabors.Shapes
/// </returns>
public static bool Equivelent(this Vector2 source1, Vector2 source2, float threshold)
{
var abs = Vector2.Abs(source1 - source2);
Vector2 abs = Vector2.Abs(source1 - source2);
return abs.X < threshold && abs.Y < threshold;
}

Просмотреть файл

@ -28,6 +28,20 @@ namespace SixLabors.Shapes
/// </summary>
int MaxIntersections { get; }
/// <summary>
/// Gets the length of the path.
/// </summary>
float Length { get; }
/// <summary>
/// Calculates the the point a certain distance a path.
/// </summary>
/// <param name="distanceAlongPath">The distance along the path to find details of.</param>
/// <returns>
/// Returns details about a point along a path.
/// </returns>
SegmentInfo PointAlongPath(float distanceAlongPath);
/// <summary>
/// Calculates the distance along and away from the path for a specified point.
/// </summary>

Просмотреть файл

@ -188,6 +188,41 @@ namespace SixLabors.Shapes
};
}
internal SegmentInfo PointAlongPath(float distanceAlongPath)
{
distanceAlongPath = distanceAlongPath % this.Length;
int pointCount = this.PointCount;
if (this.closedPath)
{
pointCount--;
}
for(int i = 0; i < pointCount; i++)
{
int next = (i + 1) % this.PointCount;
if(distanceAlongPath < this.points[next].Length)
{
float t = distanceAlongPath / this.points[next].Length;
Vector2 point = (this.points[i].Point * (1 - t)) + (this.points[next].Point * t);
Vector2 diff = this.points[i].Point - this.points[next].Point;
return new SegmentInfo
{
Point = point,
Angle = (float)(Math.Atan2(diff.Y, diff.X) % (Math.PI * 2))
};
}
else
{
distanceAlongPath -= this.points[next].Length;
}
}
throw new InvalidOperationException("should alwys reach a point along the path");
}
/// <summary>
/// Based on a line described by <paramref name="start" /> and <paramref name="end" />
/// populates a buffer for all points on the path that the line intersects.
@ -200,9 +235,14 @@ namespace SixLabors.Shapes
/// <returns>number of intersections hit</returns>
public int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset)
{
if(this.points.Length < 2)
{
return 0;
}
ClampPoints(ref start, ref end);
var target = new Segment(start, end);
Segment target = new Segment(start, end);
int polyCorners = this.points.Length;
@ -229,7 +269,7 @@ namespace SixLabors.Shapes
Segment edge = this.points[i].Segment;
// shift all orientations along but one place and fill in the last one
var pointOrientation = nextOrientation;
Orientation pointOrientation = nextOrientation;
nextOrientation = nextPlus1Orientation;
nextPlus1Orientation = CalulateOrientation(start, end, this.points[(i + 2) % this.points.Length].Point);
@ -276,9 +316,12 @@ namespace SixLabors.Shapes
int next = (i + 1) % this.points.Length;
if (precaclulate[i].RemoveLastIntersectionAndSkip)
{
if (position > 0)
{
position--;
count++;
}
continue;
}
if (precaclulate[i].DoIntersect)
@ -493,7 +536,7 @@ namespace SixLabors.Shapes
float x = (((x2 - x1) * ((x3 * y4) - (x4 * y3))) - ((x4 - x3) * ((x1 * y2) - (x2 * y1)))) / inter;
float y = (((y3 - y4) * ((x1 * y2) - (x2 * y1))) - ((y1 - y2) * ((x3 * y4) - (x4 * y3)))) / inter;
var point = new Vector2(x, y);
Vector2 point = new Vector2(x, y);
if (IsOnSegment(source, point) && IsOnSegment(target, point))
{
@ -507,6 +550,7 @@ namespace SixLabors.Shapes
/// Simplifies the collection of segments.
/// </summary>
/// <param name="segments">The segments.</param>
/// <param name="isClosed">Weather the path is closed or open.</param>
/// <returns>
/// The <see cref="T:Vector2[]"/>.
/// </returns>
@ -605,10 +649,10 @@ namespace SixLabors.Shapes
results.RemoveAt(results.Count - 1);
}
var data = results.ToArray();
for (var i = 0; i< data.Length; i++)
PointData[] data = results.ToArray();
for (int i = 0; i< data.Length; i++)
{
var next = (i + 1) % data.Length;
int next = (i + 1) % data.Length;
data[i].Segment = new Segment(data[i].Point, data[next].Point);
}

Просмотреть файл

@ -99,9 +99,9 @@ namespace SixLabors.Shapes
return this;
}
var points = new Vector2[this.points.Length];
var i = 0;
foreach (var p in this.points)
Vector2[] points = new Vector2[this.points.Length];
int i = 0;
foreach (Vector2 p in this.points)
{
points[i++] = Vector2.Transform(p, matrix);
}

Просмотреть файл

@ -0,0 +1,176 @@
using ClipperLib;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Numerics;
using System.Text;
namespace SixLabors.Shapes
{
/// <summary>
/// Path extensions to generate outlines of paths.
/// </summary>
public static class Outliner
{
private const float ScalingFactor = 1000.0f;
/// <summary>
/// Generates a outline of the path with alternating on and off segments based on the pattern.
/// </summary>
/// <param name="path">the path to outline</param>
/// <param name="width">The final width outline</param>
/// <param name="pattern">The pattern made of multiples of the width.</param>
/// <returns>A new path representing the outline.</returns>
public static IPath GenerateOutline(this IPath path, float width, float[] pattern)
{
return path.GenerateOutline(width, pattern, false);
}
/// <summary>
/// Generates a outline of the path with alternating on and off segments based on the pattern.
/// </summary>
/// <param name="path">the path to outline</param>
/// <param name="width">The final width outline</param>
/// <param name="pattern">The pattern made of multiples of the width.</param>
/// <param name="startOff">Weather the first item in the pattern is on or off.</param>
/// <returns>A new path representing the outline.</returns>
public static IPath GenerateOutline(this IPath path, float width, float[] pattern, bool startOff)
{
if (pattern == null || pattern.Length < 2)
{
return path.GenerateOutline(width);
}
ImmutableArray<ISimplePath> paths = path.Flatten();
ClipperOffset offset = new ClipperOffset();
List<IntPoint> buffer = new List<IntPoint>(3);
foreach (ISimplePath p in paths)
{
bool online = !startOff;
float targetLength = pattern[0] * width;
int patternPos = 0;
// create a new list of points representing the new outline
int pCount = p.Points.Length;
if (!p.IsClosed)
{
pCount--;
}
int i = 0;
Vector2 currentPoint = p.Points[0];
while (i < pCount)
{
int next = (i + 1) % p.Points.Length;
Vector2 targetPoint = p.Points[next];
float distToNext = Vector2.Distance(currentPoint, targetPoint);
if (distToNext > targetLength)
{
// find a point between the 2
float t = targetLength / distToNext;
Vector2 point = (currentPoint * (1 - t)) + (targetPoint * t);
buffer.Add(currentPoint.ToPoint());
buffer.Add(point.ToPoint());
// we now inset a line joining
if (online)
{
offset.AddPath(buffer, JoinType.jtSquare, EndType.etOpenButt);
}
online = !online;
buffer.Clear();
currentPoint = point;
// next length
patternPos = (patternPos + 1) % pattern.Length;
targetLength = pattern[patternPos] * width;
}
else if (distToNext <= targetLength)
{
buffer.Add(currentPoint.ToPoint());
currentPoint = targetPoint;
i++;
targetLength -= distToNext;
}
}
if (buffer.Count > 0)
{
if (p.IsClosed)
{
buffer.Add(p.Points.First().ToPoint());
}
else
{
buffer.Add(p.Points.Last().ToPoint());
}
if (online)
{
offset.AddPath(buffer, JoinType.jtSquare, EndType.etOpenButt);
}
online = !online;
buffer.Clear();
patternPos = (patternPos + 1) % pattern.Length;
targetLength = pattern[patternPos] * width;
}
}
return ExecuteOutliner(width, offset);
}
/// <summary>
/// Generates a solid outline of the path.
/// </summary>
/// <param name="path">the path to outline</param>
/// <param name="width">The final width outline</param>
/// <returns>A new path representing the outline.</returns>
public static IPath GenerateOutline(this IPath path, float width)
{
ClipperOffset offset = new ClipperLib.ClipperOffset();
//pattern can be applied to the path by cutting it into segments
System.Collections.Immutable.ImmutableArray<ISimplePath> paths = path.Flatten();
foreach (ISimplePath p in paths)
{
System.Collections.Immutable.ImmutableArray<Vector2> vectors = p.Points;
List<IntPoint> points = new List<ClipperLib.IntPoint>(vectors.Length);
foreach (Vector2 v in vectors)
{
points.Add(new IntPoint(v.X * ScalingFactor, v.Y * ScalingFactor));
}
EndType type = p.IsClosed ? EndType.etClosedLine : EndType.etOpenButt;
offset.AddPath(points, JoinType.jtMiter, type);
}
return ExecuteOutliner(width, offset);
}
private static IPath ExecuteOutliner(float width, ClipperOffset offset)
{
List<List<IntPoint>> tree = new List<List<IntPoint>>();
offset.Execute(ref tree, width * ScalingFactor / 2);
List<Polygon> polygons = new List<Polygon>();
foreach (List<IntPoint> pt in tree)
{
Vector2[] points = pt.Select(p => new Vector2(p.X / ScalingFactor, p.Y / ScalingFactor)).ToArray();
polygons.Add(new Polygon(new LinearLineSegment(points)));
}
return new ComplexPolygon(polygons.ToArray());
}
private static IntPoint ToPoint(this Vector2 vector)
{
return new IntPoint(vector.X * ScalingFactor, vector.Y * ScalingFactor);
}
}
}

Просмотреть файл

@ -47,6 +47,11 @@ namespace SixLabors.Shapes
this.flatPath = ImmutableArray.Create<ISimplePath>(this);
}
/// <summary>
/// Gets the length of the path.
/// </summary>
public float Length => this.innerPath.Length;
/// <summary>
/// Gets a value indicating whether this instance is a closed path.
/// </summary>
@ -83,7 +88,7 @@ namespace SixLabors.Shapes
/// <inheritdoc />
public PointInfo Distance(Vector2 point)
{
var dist = this.innerPath.DistanceFromPath(point);
PointInfo dist = this.innerPath.DistanceFromPath(point);
if (this.IsClosed)
{
@ -111,9 +116,9 @@ namespace SixLabors.Shapes
return this;
}
var segments = new ILineSegment[this.LineSegments.Length];
var i = 0;
foreach (var s in this.LineSegments)
ILineSegment[] segments = new ILineSegment[this.LineSegments.Length];
int i = 0;
foreach (ILineSegment s in this.LineSegments)
{
segments[i++] = s.Transform(matrix);
}
@ -176,5 +181,17 @@ namespace SixLabors.Shapes
{
return this.innerPath.PointInPolygon(point);
}
/// <summary>
/// Calculates the the point a certain distance a path.
/// </summary>
/// <param name="distanceAlongPath">The distance along the path to find details of.</param>
/// <returns>
/// Returns details about a point along a path.
/// </returns>
public SegmentInfo PointAlongPath(float distanceAlongPath)
{
return this.innerPath.PointAlongPath(distanceAlongPath);
}
}
}

Просмотреть файл

@ -179,7 +179,7 @@ namespace SixLabors.Shapes
/// </summary>
public void CloseAllFigures()
{
foreach (var f in this.figures)
foreach (Figure f in this.figures)
{
f.IsClosed = true;
}
@ -193,7 +193,7 @@ namespace SixLabors.Shapes
/// <returns>The current set of operations as a complex polygon</returns>
public IPath Build()
{
var paths = this.figures.Where(x => !x.IsEmpty).Select(x => x.Build()).ToArray();
IPath[] paths = this.figures.Where(x => !x.IsEmpty).Select(x => x.Build()).ToArray();
if (paths.Length == 1)
{
return paths[0];

Просмотреть файл

@ -164,12 +164,12 @@ namespace SixLabors.Shapes
/// </returns>
public static IEnumerable<Vector2> FindIntersections(this IPath path, Vector2 start, Vector2 end)
{
var buffer = ArrayPool<Vector2>.Shared.Rent(path.MaxIntersections);
Vector2[] buffer = ArrayPool<Vector2>.Shared.Rent(path.MaxIntersections);
try
{
var hits = path.FindIntersections(start, end, buffer, path.MaxIntersections, 0);
var results = new Vector2[hits];
for (var i = 0; i < hits; i++)
int hits = path.FindIntersections(start, end, buffer, path.MaxIntersections, 0);
Vector2[] results = new Vector2[hits];
for (int i = 0; i < hits; i++)
{
results[i] = buffer[i];
}

Просмотреть файл

@ -72,9 +72,9 @@ namespace SixLabors.Shapes
return this;
}
var segments = new ILineSegment[this.LineSegments.Length];
var i = 0;
foreach (var s in this.LineSegments)
ILineSegment[] segments = new ILineSegment[this.LineSegments.Length];
int i = 0;
foreach (ILineSegment s in this.LineSegments)
{
segments[i++] = s.Transform(matrix);
}

Просмотреть файл

@ -64,10 +64,10 @@ namespace SixLabors.Shapes.PolygonClipper
}
IPath[] shapes = new IPath[results.Count];
for (var i = 0; i < results.Count; i++)
for (int i = 0; i < results.Count; i++)
{
var source = results[i].Source;
var path = source as IPath;
object source = results[i].Source;
IPath path = source as IPath;
if (path != null)
{
@ -75,10 +75,10 @@ namespace SixLabors.Shapes.PolygonClipper
}
else
{
var points = new Vector2[results[i].Contour.Count];
for (var j = 0; j < results[i].Contour.Count; j++)
Vector2[] points = new Vector2[results[i].Contour.Count];
for (int j = 0; j < results[i].Contour.Count; j++)
{
var p = results[i].Contour[j];
IntPoint p = results[i].Contour[j];
// to make the floating point polygons compatable with clipper we had
// to scale them up to make them ints but still retain some level of precision
@ -107,7 +107,7 @@ namespace SixLabors.Shapes.PolygonClipper
public void AddPaths(IEnumerable<ClipablePath> paths)
{
Guard.NotNull(paths, nameof(paths));
foreach (var p in paths)
foreach (ClipablePath p in paths)
{
this.AddPath(p.Path, p.Type);
}
@ -121,7 +121,7 @@ namespace SixLabors.Shapes.PolygonClipper
public void AddPaths(IEnumerable<IPath> paths, ClippingType clippingType)
{
Guard.NotNull(paths, nameof(paths));
foreach (var p in paths)
foreach (IPath p in paths)
{
this.AddPath(p, clippingType);
}
@ -135,7 +135,7 @@ namespace SixLabors.Shapes.PolygonClipper
public void AddPath(IPath path, ClippingType clippingType)
{
Guard.NotNull(path, nameof(path));
foreach (var p in path.Flatten())
foreach (ISimplePath p in path.Flatten())
{
this.AddPath(p, clippingType);
}
@ -149,9 +149,9 @@ namespace SixLabors.Shapes.PolygonClipper
/// <exception cref="ClipperException">AddPath: Open paths have been disabled.</exception>
internal void AddPath(ISimplePath path, ClippingType clippingType)
{
var vectors = path.Points;
ImmutableArray<Vector2> vectors = path.Points;
List<IntPoint> points = new List<ClipperLib.IntPoint>(vectors.Length);
foreach (var v in vectors)
foreach (Vector2 v in vectors)
{
points.Add(new IntPoint(v.X * ScalingFactor, v.Y * ScalingFactor));
}

Просмотреть файл

@ -137,6 +137,9 @@ namespace SixLabors.Shapes
/// </value>
Rectangle IPath.Bounds => this;
/// <inheritdoc />
float IPath.Length => this.length;
/// <summary>
/// Gets the maximum number intersections that a shape can have when testing a line.
/// </summary>
@ -267,6 +270,59 @@ namespace SixLabors.Shapes
return new Polygon(new LinearLineSegment(this.points).Transform(matrix));
}
/// <inheritdoc />
SegmentInfo IPath.PointAlongPath(float distanceAlongPath)
{
distanceAlongPath = distanceAlongPath % this.length;
if (distanceAlongPath < this.Width)
{
// we are on the top stretch
return new SegmentInfo
{
Point = new Vector2(this.Left + distanceAlongPath, this.Top),
Angle = (float)Math.PI
};
}
else
{
distanceAlongPath -= this.Width;
if (distanceAlongPath < this.Height)
{
// down on right
return new SegmentInfo
{
Point = new Vector2(this.Right, this.Top + distanceAlongPath),
Angle = -(float)Math.PI / 2
};
}
else
{
distanceAlongPath -= this.Height;
if (distanceAlongPath < this.Width)
{
// botom right to left
return new SegmentInfo
{
Point = new Vector2(this.Right - distanceAlongPath, this.Bottom),
Angle = 0
};
}
else
{
distanceAlongPath -= this.Width;
return new SegmentInfo
{
Point = new Vector2(this.Left, this.Bottom - distanceAlongPath),
Angle = (float)(Math.PI / 2)
};
}
}
}
}
/// <summary>
/// Calculates the distance along and away from the path for a specified point.
/// </summary>

Просмотреть файл

@ -75,7 +75,7 @@ namespace SixLabors.Shapes
float anglePerSegemnts = (float)((2 * Math.PI) / verticies);
float current = angle;
Vector2[] points = new Vector2[verticies];
for (var i = 0; i < verticies; i++)
for (int i = 0; i < verticies; i++)
{
Vector2 rotated = Vector2.Transform(distanceVector, Matrix3x2.CreateRotation(current));

Просмотреть файл

@ -0,0 +1,25 @@
// <copyright file="PointInfo.cs" company="Scott Williams">
// Copyright (c) Scott Williams and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace SixLabors.Shapes
{
using System.Numerics;
/// <summary>
/// Returns meta data about the nearest point on a path from a vector
/// </summary>
public struct SegmentInfo
{
/// <summary>
/// The point on the path
/// </summary>
public Vector2 Point;
/// <summary>
/// The angle of the segment.
/// </summary>
public float Angle;
}
}

Просмотреть файл

@ -78,12 +78,12 @@ namespace SixLabors.Shapes
Vector2 distanceVectorInner = new Vector2(0, innerRadii);
Vector2 distanceVectorOuter = new Vector2(0, outerRadii);
var verticies = prongs * 2;
int verticies = prongs * 2;
float anglePerSegemnts = (float)((2 * Math.PI) / verticies);
float current = angle;
Vector2[] points = new Vector2[verticies];
var distance = distanceVectorInner;
for (var i = 0; i < verticies; i++)
Vector2 distance = distanceVectorInner;
for (int i = 0; i < verticies; i++)
{
if (distance == distanceVectorInner)
{

Просмотреть файл

@ -23,9 +23,9 @@ namespace SixLabors.Shapes.Benchmarks
public Vector2[] Internal_Old()
{
Vector2[] buffer = new Vector2[vectors.Length];
var path = new InternalPath_Old(vectors, true);
InternalPath_Old path = new InternalPath_Old(vectors, true);
for (var y = path.Bounds.Top; y < path.Bounds.Bottom; y += (1f / 32f))
for (float y = path.Bounds.Top; y < path.Bounds.Bottom; y += (1f / 32f))
{
path.FindIntersections(new Vector2(path.Bounds.Left - 1, y), new Vector2(path.Bounds.Right + 1, y), buffer, path.PointCount, 0);
}
@ -36,9 +36,9 @@ namespace SixLabors.Shapes.Benchmarks
public Vector2[] Internal_Current()
{
Vector2[] buffer = new Vector2[vectors.Length];
var path = new InternalPath(vectors, true);
InternalPath path = new InternalPath(vectors, true);
for (var y = path.Bounds.Top; y < path.Bounds.Bottom; y += (1f / 32f))
for (float y = path.Bounds.Top; y < path.Bounds.Bottom; y += (1f / 32f))
{
path.FindIntersections(new Vector2(path.Bounds.Left - 1, y), new Vector2(path.Bounds.Right + 1, y), buffer, path.PointCount, 0);
}

Просмотреть файл

@ -277,11 +277,11 @@ namespace SixLabors.Shapes
{
// lines are colinear and intersect
// if this is the case we need to tell if this is an inflection or not
var nextSide = Side.Same;
Side nextSide = Side.Same;
// keep going next untill we are no longer on the line
while (nextSide == Side.Same)
{
var nextPlus1 = FindNextPoint(polyCorners, next);
int nextPlus1 = FindNextPoint(polyCorners, next);
nextSide = SideOfLine(this.points[nextPlus1], this.points[i], this.points[next]);
if (nextSide == Side.Same)
{
@ -298,7 +298,7 @@ namespace SixLabors.Shapes
}
}
var prevSide = SideOfLine(this.points[lastCorner], this.points[i], this.points[next]);
Side prevSide = SideOfLine(this.points[lastCorner], this.points[i], this.points[next]);
if (prevSide != nextSide)
{
position--;
@ -327,8 +327,8 @@ namespace SixLabors.Shapes
last = i;
}
var side = SideOfLine(this.points[last], start, end);
var side2 = SideOfLine(this.points[next], start, end);
Side side = SideOfLine(this.points[last], start, end);
Side side2 = SideOfLine(this.points[next], start, end);
if (side == Side.Same && side2 == Side.Same)
{
@ -406,17 +406,17 @@ namespace SixLabors.Shapes
}
// if it hit any points then class it as inside
var buffer = ArrayPool<Vector2>.Shared.Rent(this.points.Length);
Vector2[] buffer = ArrayPool<Vector2>.Shared.Rent(this.points.Length);
try
{
var intersection = this.FindIntersections(point, new Vector2(this.Bounds.Left - 1, this.Bounds.Top - 1), buffer, this.points.Length, 0);
int intersection = this.FindIntersections(point, new Vector2(this.Bounds.Left - 1, this.Bounds.Top - 1), buffer, this.points.Length, 0);
if (intersection % 2 == 1)
{
return true;
}
// check if the point is on an intersection is it is then inside
for (var i = 0; i < intersection; i++)
for (int i = 0; i < intersection; i++)
{
if (buffer[i].Equivelent(point, Epsilon))
{
@ -434,8 +434,8 @@ namespace SixLabors.Shapes
private static Side SideOfLine(Vector2 test, Vector2 lineStart, Vector2 lineEnd)
{
var testDiff = test - lineStart;
var lineDiff = lineEnd - lineStart;
Vector2 testDiff = test - lineStart;
Vector2 lineDiff = lineEnd - lineStart;
if (float.IsInfinity(lineDiff.X))
{
if (lineDiff.X > 0)
@ -460,7 +460,7 @@ namespace SixLabors.Shapes
}
}
var crossProduct = (lineDiff.X * testDiff.Y) - (lineDiff.Y * testDiff.X);
float crossProduct = (lineDiff.X * testDiff.Y) - (lineDiff.Y * testDiff.X);
if (crossProduct > -Epsilon && crossProduct < Epsilon)
{
@ -479,10 +479,10 @@ namespace SixLabors.Shapes
{
// Find the four orientations needed for general and
// special cases
var o1 = CalulateOrientation(p1, q1, p2);
var o2 = CalulateOrientation(p1, q1, q2);
var o3 = CalulateOrientation(p2, q2, p1);
var o4 = CalulateOrientation(p2, q2, q1);
Orientation o1 = CalulateOrientation(p1, q1, p2);
Orientation o2 = CalulateOrientation(p1, q1, q2);
Orientation o3 = CalulateOrientation(p2, q2, p1);
Orientation o4 = CalulateOrientation(p2, q2, q1);
// General case
if (o1 != o2 && o3 != o4)

Просмотреть файл

@ -233,7 +233,7 @@ namespace SixLabors.Shapes
Vector2 edgeStart = this.points[i].Point;
Vector2 edgeEnd = this.points[next].Point;
var pointOrientation = nextOrientation;
Orientation pointOrientation = nextOrientation;
nextOrientation = nextPlus1Orientation;
nextPlus1Orientation = CalulateOrientation(start, end, this.points[nextPlus1].Point);
@ -499,7 +499,7 @@ namespace SixLabors.Shapes
float x = (((x2 - x1) * ((x3 * y4) - (x4 * y3))) - ((x4 - x3) * ((x1 * y2) - (x2 * y1)))) / inter;
float y = (((y3 - y4) * ((x1 * y2) - (x2 * y1))) - ((y1 - y2) * ((x3 * y4) - (x4 * y3)))) / inter;
var point = new Vector2(x, y);
Vector2 point = new Vector2(x, y);
if (IsOnSegment(line1Start, point, line1End) && IsOnSegment(line2Start, point, line2End))
{

Просмотреть файл

@ -13,8 +13,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void SingleSegmentConstructor()
{
var segment = new BezierLineSegment(new Vector2(0, 0), new Vector2(10, 0), new Vector2(10, 0), new Vector2(20, 0));
var points = segment.Flatten();
BezierLineSegment segment = new BezierLineSegment(new Vector2(0, 0), new Vector2(10, 0), new Vector2(10, 0), new Vector2(20, 0));
System.Collections.Immutable.ImmutableArray<Vector2> points = segment.Flatten();
Assert.Contains(new Vector2(0, 0), points);
Assert.Contains(new Vector2(10, 0), points);
Assert.Contains(new Vector2(20, 0), points);
@ -23,7 +23,7 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MustHaveAtleast4Points()
{
var error = Assert.Throws<ArgumentOutOfRangeException>(() => new BezierLineSegment(new[] { new Vector2(0, 0) }));
ArgumentOutOfRangeException error = Assert.Throws<ArgumentOutOfRangeException>(() => new BezierLineSegment(new[] { new Vector2(0, 0) }));
}
}
}

Просмотреть файл

@ -14,7 +14,7 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MissingIntersection()
{
var data = new float[6];
float[] data = new float[6];
Polygon simplePath = new Polygon(new LinearLineSegment(
new Vector2(10, 10),
new Vector2(200, 150),
@ -25,11 +25,11 @@ namespace SixLabors.Shapes.Tests
new Vector2(37, 85),
new Vector2(93, 85)));
var intersections1 = ScanY(hole1, 137, data, 6, 0);
int intersections1 = ScanY(hole1, 137, data, 6, 0);
Assert.Equal(2, intersections1);
var poly = simplePath.Clip(hole1);
IPath poly = simplePath.Clip(hole1);
var intersections = ScanY(poly, 137, data, 6, 0);
int intersections = ScanY(poly, 137, data, 6, 0);
// returns an even number of points
Assert.Equal(4, intersections);
@ -60,24 +60,24 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MissingIntersectionsOpenSans_a()
{
var path = @"36.57813x49.16406 35.41797x43.67969 35.41797x43.67969 35.13672x43.67969 35.13672x43.67969 34.41629x44.54843 33.69641x45.34412 32.97708x46.06674 32.2583x46.71631 31.54007x47.29282 30.82239x47.79626 30.10526x48.22665 29.38867x48.58398 29.38867x48.58398 28.65012x48.88474 27.86707x49.14539 27.03952x49.36594 26.16748x49.54639 25.25095x49.68674 24.28992x49.78699 23.28439x49.84714 22.23438x49.86719 22.23438x49.86719 21.52775x49.85564 20.84048x49.82104 20.17258x49.76337 19.52405x49.68262 18.28506x49.4519 17.12354x49.12891 16.03946x48.71362 15.03284x48.20605 14.10367x47.6062 13.25195x46.91406 13.25195x46.91406 12.48978x46.13678 11.82922x45.28149 11.27029x44.34821 10.81299x43.33691 10.45731x42.24762 10.20325x41.08032 10.05081x39.83502 10.0127x39.18312 10x38.51172 10x38.51172 10.01823x37.79307 10.07292x37.09613 10.16407x36.42088 10.29169x35.76733 10.6563x34.52533 11.16675x33.37012 11.82304x32.3017 12.62518x31.32007 13.57317x30.42523 14.10185x30.01036 14.66699x29.61719 15.2686x29.24571 15.90666x28.89594 16.58119x28.56786 17.29218x28.26147 18.03962x27.97679 18.82353x27.71381 19.6439x27.47252 20.50073x27.25293 22.32378x26.87885 24.29266x26.59155 26.40739x26.39105 28.66797x26.27734 28.66797x26.27734 35.20703x26.06641 35.20703x26.06641 35.20703x23.67578 35.20703x23.67578 35.17654x22.57907 35.08508x21.55652 34.93265x20.60812 34.71924x19.73389 34.44485x18.93381 34.1095x18.20789 33.71317x17.55612 33.25586x16.97852 33.25586x16.97852 32.73154x16.47177 32.13416x16.03259 31.46371x15.66098 30.72021x15.35693 29.90366x15.12045 29.01404x14.95154 28.05136x14.85019 27.01563x14.81641 27.01563x14.81641 25.79175x14.86255 24.52832x15.00098 23.88177x15.1048 23.22534x15.23169 21.88281x15.55469 20.50073x15.96997 19.0791x16.47754 17.61792x17.07739 16.11719x17.76953 16.11719x17.76953 14.32422x13.30469 14.32422x13.30469 15.04465x12.92841 15.7821x12.573 17.30811x11.9248 18.90222x11.36011 20.56445x10.87891 20.56445x10.87891 22.26184x10.49438 23.96143x10.21973 24.81204x10.1236 25.66321x10.05493 26.51492x10.01373 27.36719x10 27.36719x10 29.03409x10.04779 29.82572x10.10753 30.58948x10.19116 31.32536x10.29869 32.03336x10.43011 32.71348x10.58543 33.36572x10.76465 34.58658x11.19476 35.69592x11.72046 36.69376x12.34174 37.58008x13.05859 37.58008x13.05859 38.35873x13.88092 39.03357x14.8186 39.60458x15.87164 40.07178x17.04004 40.26644x17.6675 40.43515x18.32379 40.5779x19.00893 40.6947x19.7229 40.78555x20.46571 40.85043x21.23737 40.88937x22.03786 40.90234x22.86719 40.90234x22.86719 40.90234x49.16406
string path = @"36.57813x49.16406 35.41797x43.67969 35.41797x43.67969 35.13672x43.67969 35.13672x43.67969 34.41629x44.54843 33.69641x45.34412 32.97708x46.06674 32.2583x46.71631 31.54007x47.29282 30.82239x47.79626 30.10526x48.22665 29.38867x48.58398 29.38867x48.58398 28.65012x48.88474 27.86707x49.14539 27.03952x49.36594 26.16748x49.54639 25.25095x49.68674 24.28992x49.78699 23.28439x49.84714 22.23438x49.86719 22.23438x49.86719 21.52775x49.85564 20.84048x49.82104 20.17258x49.76337 19.52405x49.68262 18.28506x49.4519 17.12354x49.12891 16.03946x48.71362 15.03284x48.20605 14.10367x47.6062 13.25195x46.91406 13.25195x46.91406 12.48978x46.13678 11.82922x45.28149 11.27029x44.34821 10.81299x43.33691 10.45731x42.24762 10.20325x41.08032 10.05081x39.83502 10.0127x39.18312 10x38.51172 10x38.51172 10.01823x37.79307 10.07292x37.09613 10.16407x36.42088 10.29169x35.76733 10.6563x34.52533 11.16675x33.37012 11.82304x32.3017 12.62518x31.32007 13.57317x30.42523 14.10185x30.01036 14.66699x29.61719 15.2686x29.24571 15.90666x28.89594 16.58119x28.56786 17.29218x28.26147 18.03962x27.97679 18.82353x27.71381 19.6439x27.47252 20.50073x27.25293 22.32378x26.87885 24.29266x26.59155 26.40739x26.39105 28.66797x26.27734 28.66797x26.27734 35.20703x26.06641 35.20703x26.06641 35.20703x23.67578 35.20703x23.67578 35.17654x22.57907 35.08508x21.55652 34.93265x20.60812 34.71924x19.73389 34.44485x18.93381 34.1095x18.20789 33.71317x17.55612 33.25586x16.97852 33.25586x16.97852 32.73154x16.47177 32.13416x16.03259 31.46371x15.66098 30.72021x15.35693 29.90366x15.12045 29.01404x14.95154 28.05136x14.85019 27.01563x14.81641 27.01563x14.81641 25.79175x14.86255 24.52832x15.00098 23.88177x15.1048 23.22534x15.23169 21.88281x15.55469 20.50073x15.96997 19.0791x16.47754 17.61792x17.07739 16.11719x17.76953 16.11719x17.76953 14.32422x13.30469 14.32422x13.30469 15.04465x12.92841 15.7821x12.573 17.30811x11.9248 18.90222x11.36011 20.56445x10.87891 20.56445x10.87891 22.26184x10.49438 23.96143x10.21973 24.81204x10.1236 25.66321x10.05493 26.51492x10.01373 27.36719x10 27.36719x10 29.03409x10.04779 29.82572x10.10753 30.58948x10.19116 31.32536x10.29869 32.03336x10.43011 32.71348x10.58543 33.36572x10.76465 34.58658x11.19476 35.69592x11.72046 36.69376x12.34174 37.58008x13.05859 37.58008x13.05859 38.35873x13.88092 39.03357x14.8186 39.60458x15.87164 40.07178x17.04004 40.26644x17.6675 40.43515x18.32379 40.5779x19.00893 40.6947x19.7229 40.78555x20.46571 40.85043x21.23737 40.88937x22.03786 40.90234x22.86719 40.90234x22.86719 40.90234x49.16406
23.39453x45.05078 24.06655x45.03911 24.72031x45.00409 25.97302x44.86401 27.15268x44.63055 28.25928x44.30371 29.29282x43.88348 30.2533x43.36987 31.14072x42.76288 31.95508x42.0625 31.95508x42.0625 32.6843x41.27808 33.31628x40.41895 33.85104x39.48511 34.28857x38.47656 34.62888x37.39331 34.87195x36.23535 35.01779x35.00269 35.06641x33.69531 35.06641x33.69531 35.06641x30.21484 35.06641x30.21484 29.23047x30.46094 29.23047x30.46094 27.55093x30.54855 25.9928x30.68835 24.55606x30.88034 23.24072x31.12451 22.04678x31.42087 20.97424x31.76941 20.0231x32.17014 19.19336x32.62305 19.19336x32.62305 18.47238x33.13528 17.84753x33.71399 17.31882x34.35916 16.88623x35.0708 16.54977x35.84891 16.30945x36.69348 16.16525x37.60452 16.11719x38.58203 16.11719x38.58203 16.14713x39.34943 16.23694x40.06958 16.38663x40.74249 16.59619x41.36816 17.19495x42.47778 18.0332x43.39844 18.0332x43.39844 19.08679x44.12134 19.68527x44.40533 20.33154x44.6377 21.0256x44.81842 21.76746x44.94751 22.5571x45.02496 23.39453x45.05078";
var paths = path.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
var polys = paths.Select(line => {
var pl = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string[] paths = path.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
Polygon[] polys = paths.Select(line => {
string[] pl = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var points = pl.Select(p => p.Split('x'))
Vector2[] points = pl.Select(p => p.Split('x'))
.Select(p => {
return new Vector2(float.Parse(p[0]), float.Parse(p[1]));
})
.ToArray();
return new Polygon(new LinearLineSegment(points));
}).ToArray();
var complex = new ComplexPolygon(polys);
ComplexPolygon complex = new ComplexPolygon(polys);
var data = new float[complex.MaxIntersections];
var intersections = ScanY(complex, 10, data, complex.MaxIntersections, 0);
float[] data = new float[complex.MaxIntersections];
int intersections = ScanY(complex, 10, data, complex.MaxIntersections, 0);
Assert.True(intersections % 2 == 0, $"even number of intersections expected but found {intersections}");
}
@ -85,24 +85,24 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MissingIntersectionsOpenSans_o()
{
var path = @"45.40234x29.93359 45.3838x31.09519 45.32819x32.22452 45.23549x33.32157 45.10571x34.38635 44.93886x35.41886 44.73492x36.4191 44.49391x37.38706 44.21582x38.32275 43.90065x39.22617 43.5484x40.09732 43.15907x40.9362 42.73267x41.7428 42.26918x42.51713 41.76862x43.25919 41.23097x43.96897 40.65625x44.64648 40.65625x44.64648 40.04884x45.28719 39.41315x45.88657 38.74916x46.4446 38.05688x46.9613 37.33632x47.43667 36.58746x47.8707 35.81032x48.26339 35.00488x48.61475 34.17116x48.92477 33.30914x49.19345 32.41884x49.4208 31.50024x49.60681 30.55336x49.75149 29.57819x49.85483 28.57472x49.91683 27.54297x49.9375 27.54297x49.9375 26.2691x49.8996 25.03149x49.78589 23.83014x49.59637 22.66504x49.33105 21.53619x48.98993 20.4436x48.573 19.38727x48.08026 18.36719x47.51172 18.36719x47.51172 17.3938x46.87231 16.47754x46.16699 15.61841x45.39575 14.81641x44.55859 14.07153x43.65552 13.38379x42.68652 12.75317x41.65161 12.17969x40.55078 12.17969x40.55078 11.66882x39.39282 11.22607x38.18652 10.85144x36.93188 10.54492x35.62891 10.30652x34.27759 10.13623x32.87793 10.03406x31.42993 10x29.93359 10x29.93359 10.0184x28.77213 10.07361x27.64322 10.16562x26.54685 10.29443x25.48303 10.46005x24.45176 10.66248x23.45303 10.9017x22.48685 11.17773x21.55322 11.49057x20.65214 11.84021x19.7836 12.22665x18.94761 12.6499x18.14417 13.10995x17.37327 13.60681x16.63492 14.14047x15.92912 14.71094x15.25586 14.71094x15.25586 15.31409x14.61941 15.9458x14.02402 16.60608x13.46969 17.29492x12.95642 18.01233x12.48421 18.7583x12.05307 19.53284x11.66299 20.33594x11.31396 21.1676x11.006 22.02783x10.73911 22.91663x10.51327 23.83398x10.32849 24.77991x10.18478 25.75439x10.08212 26.75745x10.02053 27.78906x10 27.78906x10 28.78683x10.02101 29.75864x10.08405 30.70449x10.1891 31.62439x10.33618 32.51833x10.52528 33.38632x10.75641 34.22836x11.02956 35.04443x11.34473 35.83456x11.70192 36.59872x12.10114 37.33694x12.54237 38.04919x13.02563 38.7355x13.55092 39.39584x14.11823 40.03024x14.72755 40.63867x15.37891 40.63867x15.37891 41.21552x16.0661 41.75516x16.78296 42.25757x17.52948 42.72278x18.30566 43.15077x19.11151 43.54153x19.94702 43.89509x20.81219 44.21143x21.70703 44.49055x22.63153 44.73245x23.58569 44.93714x24.56952 45.10461x25.58301 45.23487x26.62616 45.32791x27.69897 45.38374x28.80145 45.40234x29.93359
string path = @"45.40234x29.93359 45.3838x31.09519 45.32819x32.22452 45.23549x33.32157 45.10571x34.38635 44.93886x35.41886 44.73492x36.4191 44.49391x37.38706 44.21582x38.32275 43.90065x39.22617 43.5484x40.09732 43.15907x40.9362 42.73267x41.7428 42.26918x42.51713 41.76862x43.25919 41.23097x43.96897 40.65625x44.64648 40.65625x44.64648 40.04884x45.28719 39.41315x45.88657 38.74916x46.4446 38.05688x46.9613 37.33632x47.43667 36.58746x47.8707 35.81032x48.26339 35.00488x48.61475 34.17116x48.92477 33.30914x49.19345 32.41884x49.4208 31.50024x49.60681 30.55336x49.75149 29.57819x49.85483 28.57472x49.91683 27.54297x49.9375 27.54297x49.9375 26.2691x49.8996 25.03149x49.78589 23.83014x49.59637 22.66504x49.33105 21.53619x48.98993 20.4436x48.573 19.38727x48.08026 18.36719x47.51172 18.36719x47.51172 17.3938x46.87231 16.47754x46.16699 15.61841x45.39575 14.81641x44.55859 14.07153x43.65552 13.38379x42.68652 12.75317x41.65161 12.17969x40.55078 12.17969x40.55078 11.66882x39.39282 11.22607x38.18652 10.85144x36.93188 10.54492x35.62891 10.30652x34.27759 10.13623x32.87793 10.03406x31.42993 10x29.93359 10x29.93359 10.0184x28.77213 10.07361x27.64322 10.16562x26.54685 10.29443x25.48303 10.46005x24.45176 10.66248x23.45303 10.9017x22.48685 11.17773x21.55322 11.49057x20.65214 11.84021x19.7836 12.22665x18.94761 12.6499x18.14417 13.10995x17.37327 13.60681x16.63492 14.14047x15.92912 14.71094x15.25586 14.71094x15.25586 15.31409x14.61941 15.9458x14.02402 16.60608x13.46969 17.29492x12.95642 18.01233x12.48421 18.7583x12.05307 19.53284x11.66299 20.33594x11.31396 21.1676x11.006 22.02783x10.73911 22.91663x10.51327 23.83398x10.32849 24.77991x10.18478 25.75439x10.08212 26.75745x10.02053 27.78906x10 27.78906x10 28.78683x10.02101 29.75864x10.08405 30.70449x10.1891 31.62439x10.33618 32.51833x10.52528 33.38632x10.75641 34.22836x11.02956 35.04443x11.34473 35.83456x11.70192 36.59872x12.10114 37.33694x12.54237 38.04919x13.02563 38.7355x13.55092 39.39584x14.11823 40.03024x14.72755 40.63867x15.37891 40.63867x15.37891 41.21552x16.0661 41.75516x16.78296 42.25757x17.52948 42.72278x18.30566 43.15077x19.11151 43.54153x19.94702 43.89509x20.81219 44.21143x21.70703 44.49055x22.63153 44.73245x23.58569 44.93714x24.56952 45.10461x25.58301 45.23487x26.62616 45.32791x27.69897 45.38374x28.80145 45.40234x29.93359
16.04688x29.93359 16.09302x31.72437 16.23145x33.40527 16.33527x34.20453 16.46216x34.97632 16.61212x35.72064 16.78516x36.4375 16.98126x37.12689 17.20044x37.78882 17.44269x38.42328 17.70801x39.03027 18.30786x40.16187 19x41.18359 19x41.18359 19.78168x42.08997 20.65015x42.87549 21.60541x43.54016 22.64746x44.08398 23.77631x44.50696 24.99194x44.80908 26.29437x44.99036 26.97813x45.03568 27.68359x45.05078 27.68359x45.05078 28.38912x45.03575 29.07309x44.99063 30.37634x44.81018 31.59335x44.50943 32.72412x44.08838 33.76865x43.54703 34.72693x42.88538 35.59897x42.10342 36.38477x41.20117 36.38477x41.20117 37.08102x40.18301 37.68445x39.05334 37.95135x38.44669 38.19504x37.81216 38.41552x37.14976 38.61279x36.45947 38.78686x35.74131 38.93771x34.99527 39.06536x34.22135 39.1698x33.41956 39.30905x31.73233 39.35547x29.93359 39.35547x29.93359 39.30905x28.15189 39.1698x26.48059 39.06536x25.68635 38.93771x24.91971 38.78686x24.18067 38.61279x23.46924 38.41552x22.78541 38.19504x22.12918 37.95135x21.50056 37.68445x20.89954 37.08102x19.7803 36.38477x18.77148 36.38477x18.77148 35.59787x17.87747 34.72253x17.10266 33.75876x16.44705 32.70654x15.91064 31.56589x15.49344 30.33679x15.19543 29.68908x15.09113 29.01926x15.01663 28.32732x14.97193 27.61328x14.95703 27.61328x14.95703 26.90796x14.97173 26.22461x15.01581 24.92383x15.19214 23.71094x15.48602 22.58594x15.89746 21.54883x16.42645 20.59961x17.073 19.73828x17.8371 18.96484x18.71875 18.96484x18.71875 18.28094x19.71686 17.68823x20.83032 17.42607x21.43031 17.18671x22.05914 16.97014x22.71681 16.77637x23.40332 16.60539x24.11867 16.45721x24.86285 16.33183x25.63588 16.22925x26.43774 16.09247x28.12799 16.04688x29.93359 ";
var paths = path.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
var polys = paths.Select(line => {
var pl = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string[] paths = path.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
Polygon[] polys = paths.Select(line => {
string[] pl = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var points = pl.Select(p => p.Split('x'))
Vector2[] points = pl.Select(p => p.Split('x'))
.Select(p => {
return new Vector2(float.Parse(p[0]), float.Parse(p[1]));
})
.ToArray();
return new Polygon(new LinearLineSegment(points));
}).ToArray();
var complex = new ComplexPolygon(polys);
ComplexPolygon complex = new ComplexPolygon(polys);
var data = new float[complex.MaxIntersections];
var intersections = ScanY(complex, 30, data, complex.MaxIntersections, 0);
float[] data = new float[complex.MaxIntersections];
int intersections = ScanY(complex, 30, data, complex.MaxIntersections, 0);
Assert.True(data[1] < 28, $"second intersection should be > 28 but was {data[1]}");

Просмотреть файл

@ -19,13 +19,13 @@ namespace SixLabors.Shapes.Tests
{
if (throws)
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Ellipse(0,0, width, 99));
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Ellipse(0,0, width, 99));
Assert.Equal("width", ex.ParamName);
}
else
{
var p = new Ellipse(0, 0, width, 99);
Ellipse p = new Ellipse(0, 0, width, 99);
Assert.NotNull(p);
}
}
@ -39,13 +39,13 @@ namespace SixLabors.Shapes.Tests
{
if (throws)
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Ellipse(0,0,99, height));
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Ellipse(0,0,99, height));
Assert.Equal("height", ex.ParamName);
}
else
{
var p = new Ellipse(0, 0, 99, height);
Ellipse p = new Ellipse(0, 0, 99, height);
Assert.NotNull(p);
}
}
@ -53,8 +53,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ClippingCornerShouldReturn2Points()
{
var poly = new Ellipse(50, 50, 30, 50);
var points = poly.FindIntersections(new Vector2(0, 75), new Vector2(100, 75)).ToArray();
Ellipse poly = new Ellipse(50, 50, 30, 50);
Vector2[] points = poly.FindIntersections(new Vector2(0, 75), new Vector2(100, 75)).ToArray();
Assert.Equal(2, points.Length);
}
@ -62,8 +62,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void AcrossEllipsShouldReturn2()
{
var poly = new Ellipse(50, 50, 30, 50);
var points = poly.FindIntersections(new Vector2(0, 49), new Vector2(100, 49)).ToArray();
Ellipse poly = new Ellipse(50, 50, 30, 50);
Vector2[] points = poly.FindIntersections(new Vector2(0, 49), new Vector2(100, 49)).ToArray();
Assert.Equal(2, points.Length);
}
@ -71,11 +71,11 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void AcrossEllipseShouldReturn2()
{
var poly = new Ellipse(0, 0, 10, 20).Scale(5);
IPath poly = new Ellipse(0, 0, 10, 20).Scale(5);
poly = poly.Translate(poly.Bounds.Location * -1) // touch top left
.Translate(new Vector2(10)); // move in from top left
var points = poly.FindIntersections(new Vector2(0, 10), new Vector2(100, 10)).ToArray();
Vector2[] points = poly.FindIntersections(new Vector2(0, 10), new Vector2(100, 10)).ToArray();
Assert.Equal(2, points.Length);
}

Просмотреть файл

@ -70,13 +70,13 @@ namespace SixLabors.Shapes.Tests
[MemberData(nameof(polygonsTheoryData))]
public void ShapeMissingEdgeHits(string name)
{
var polygon = shapes[name];
var top = (int)Math.Ceiling(polygon.Bounds.Top);
var bottom = (int)Math.Floor(polygon.Bounds.Bottom);
IPath polygon = shapes[name];
int top = (int)Math.Ceiling(polygon.Bounds.Top);
int bottom = (int)Math.Floor(polygon.Bounds.Bottom);
for (var y = top; y <= bottom; y++)
for (int y = top; y <= bottom; y++)
{
var intersections = polygon.FindIntersections(new Vector2(polygon.Bounds.Left - 1, y), new Vector2(polygon.Bounds.Right + 1, y));
IEnumerable<Vector2> intersections = polygon.FindIntersections(new Vector2(polygon.Bounds.Left - 1, y), new Vector2(polygon.Bounds.Right + 1, y));
if (intersections.Count() % 2 != 0)
{
Assert.True(false, $"crosssection of '{name}' at '{y}' produced {intersections.Count()} number of intersections");
@ -105,9 +105,9 @@ namespace SixLabors.Shapes.Tests
[MemberData(nameof(specificErrors))]
public void SpecificMisses(string name, int yScanLine)
{
var polygon = shapes[name];
IPath polygon = shapes[name];
var intersections = polygon.FindIntersections(new Vector2(polygon.Bounds.Left - 1, yScanLine), new Vector2(polygon.Bounds.Right + 1, yScanLine)).Count();
int intersections = polygon.FindIntersections(new Vector2(polygon.Bounds.Left - 1, yScanLine), new Vector2(polygon.Bounds.Right + 1, yScanLine)).Count();
Assert.True(intersections % 2 == 0, $"crosssection of '{name}' at '{yScanLine}' produced {intersections} intersections");
}

Просмотреть файл

@ -2,6 +2,7 @@
namespace SixLabors.Shapes.Tests
{
using System;
using System.Linq;
using System.Numerics;
@ -13,10 +14,10 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MultipleLineSegmentsSimplePathsAreMerged()
{
var seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(2, 2));
var seg2 = new LinearLineSegment(new Vector2(4, 4), new Vector2(5, 5));
LinearLineSegment seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(2, 2));
LinearLineSegment seg2 = new LinearLineSegment(new Vector2(4, 4), new Vector2(5, 5));
var path = new InternalPath(new ILineSegment[] { seg1, seg2 }, true);
InternalPath path = new InternalPath(new ILineSegment[] { seg1, seg2 }, true);
Assert.Contains(new Vector2(0, 0), path.Points());
Assert.DoesNotContain(new Vector2(2, 2), path.Points());
@ -27,9 +28,9 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Length_Closed()
{
var seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 2));
LinearLineSegment seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 2));
var path = new InternalPath(seg1, true);
InternalPath path = new InternalPath(seg1, true);
Assert.Equal(4, path.Length);
}
@ -37,9 +38,9 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Length_Open()
{
var seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 2));
LinearLineSegment seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 2));
var path = new InternalPath(seg1, false);
InternalPath path = new InternalPath(seg1, false);
Assert.Equal(2, path.Length);
}
@ -47,10 +48,10 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Bounds()
{
var seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(2, 2));
var seg2 = new LinearLineSegment(new Vector2(4, 4), new Vector2(5, 5));
LinearLineSegment seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(2, 2));
LinearLineSegment seg2 = new LinearLineSegment(new Vector2(4, 4), new Vector2(5, 5));
var path = new InternalPath(new ILineSegment[] { seg1, seg2 }, true);
InternalPath path = new InternalPath(new ILineSegment[] { seg1, seg2 }, true);
Assert.Equal(0, path.Bounds.Left);
Assert.Equal(5, path.Bounds.Right);
@ -60,8 +61,8 @@ namespace SixLabors.Shapes.Tests
private static InternalPath Create(Vector2 location, Size size, bool closed = true)
{
var seg1 = new LinearLineSegment(location, location + new Vector2(size.Width, 0));
var seg2 = new LinearLineSegment(location + new Vector2(size.Width, size.Height), location + new Vector2(0, size.Height));
LinearLineSegment seg1 = new LinearLineSegment(location, location + new Vector2(size.Width, 0));
LinearLineSegment seg2 = new LinearLineSegment(location + new Vector2(size.Width, size.Height), location + new Vector2(0, size.Height));
return new InternalPath(new ILineSegment[] { seg1, seg2 }, closed);
}
@ -118,28 +119,47 @@ namespace SixLabors.Shapes.Tests
[MemberData(nameof(PointInPolygonTheoryData))]
public void PointInPolygon(TestPoint location, TestSize size, TestPoint point, bool isInside)
{
var shape = Create(location, size);
InternalPath shape = Create(location, size);
Assert.Equal(isInside, shape.PointInPolygon(point));
}
[Fact]
public void PointInPolygon_OpenPath()
{
var seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(10, 10), new Vector2(10, 0));
LinearLineSegment seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(10, 10), new Vector2(10, 0));
var p = new InternalPath(seg1, false);
InternalPath p = new InternalPath(seg1, false);
Assert.False(p.PointInPolygon(new Vector2(5, 5)));
var p2 = new InternalPath(seg1, true);
InternalPath p2 = new InternalPath(seg1, true);
Assert.True(p2.PointInPolygon(new Vector2(5, 5f)));
}
const float HalfPi = (float)(Math.PI / 2);
const float Pi = (float)(Math.PI);
[Theory]
[InlineData(0, 50, 50, Pi)]
[InlineData(100, 150, 50, Pi)]
[InlineData(200, 250, 50, -HalfPi)]
[InlineData(259, 250, 109, -HalfPi)]
[InlineData(261, 249, 110, 0)]
[InlineData(620, 150, 50, Pi)] // wrap about end of path
public void PointOnPath(float distance, float expectedX, float expectedY, float expectedAngle)
{
InternalPath shape = Create(new Vector2(50, 50), new Size(200, 60));
var point = shape.PointAlongPath(distance);
Assert.Equal(expectedX, point.Point.X, 4);
Assert.Equal(expectedY, point.Point.Y, 4);
Assert.Equal(expectedAngle, point.Angle, 4);
}
[Theory]
[MemberData(nameof(PathDistanceTheoryData))]
public void DistanceFromPath_Path(TestPoint point, float expectedDistance, float alongPath)
{
var shape = Create(new Vector2(0, 0), new Size(10, 10));
var info = shape.DistanceFromPath(point);
InternalPath shape = Create(new Vector2(0, 0), new Size(10, 10));
PointInfo info = shape.DistanceFromPath(point);
Assert.Equal(expectedDistance, info.DistanceFromPath);
Assert.Equal(alongPath, info.DistanceAlongPath);
}
@ -147,8 +167,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void DistanceFromPath_Path_Closed()
{
var shape = Create(new Vector2(0, 0), new Size(10, 10), false);
var info = shape.DistanceFromPath(new Vector2(5, 5));
InternalPath shape = Create(new Vector2(0, 0), new Size(10, 10), false);
PointInfo info = shape.DistanceFromPath(new Vector2(5, 5));
Assert.Equal(5, info.DistanceFromPath);
Assert.Equal(5, info.DistanceAlongPath);
}
@ -156,9 +176,9 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Intersections_buffer()
{
var shape = Create(new Vector2(0, 0), new Size(10, 10));
var buffer = new Vector2[shape.PointCount];
var hits = shape.FindIntersections(new Vector2(5, -10), new Vector2(5, 20), buffer, 4, 0);
InternalPath shape = Create(new Vector2(0, 0), new Size(10, 10));
Vector2[] buffer = new Vector2[shape.PointCount];
int hits = shape.FindIntersections(new Vector2(5, -10), new Vector2(5, 20), buffer, 4, 0);
Assert.Equal(2, hits);
Assert.Equal(new Vector2(5, 0), buffer[0]);
@ -168,8 +188,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Intersections_enumerabe()
{
var shape = Create(new Vector2(0, 0), new Size(10, 10));
var buffer = shape.FindIntersections(new Vector2(5, -10), new Vector2(5, 20)).ToArray();
InternalPath shape = Create(new Vector2(0, 0), new Size(10, 10));
Vector2[] buffer = shape.FindIntersections(new Vector2(5, -10), new Vector2(5, 20)).ToArray();
Assert.Equal(2, buffer.Length);
Assert.Equal(new Vector2(5, 0), buffer[0]);
@ -179,8 +199,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Intersections_enumerabe_openpath()
{
var shape = Create(new Vector2(0, 0), new Size(10, 10), false);
var buffer = shape.FindIntersections(new Vector2(5, -10), new Vector2(5, 20)).ToArray();
InternalPath shape = Create(new Vector2(0, 0), new Size(10, 10), false);
Vector2[] buffer = shape.FindIntersections(new Vector2(5, -10), new Vector2(5, 20)).ToArray();
Assert.Equal(2, buffer.Length);
Assert.Equal(new Vector2(5, 0), buffer[0]);
@ -190,9 +210,9 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Intersections_Diagonal()
{
var shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 10)), false);
InternalPath shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 10)), false);
var buffer = shape.FindIntersections(new Vector2(0, 10), new Vector2(10, 0)).ToArray();
Vector2[] buffer = shape.FindIntersections(new Vector2(0, 10), new Vector2(10, 0)).ToArray();
Assert.Equal(1, buffer.Length);
Assert.Equal(new Vector2(5, 5), buffer[0]);
@ -201,18 +221,18 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Intersections_Diagonal_NoHit()
{
var shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(4, 4)), false);
InternalPath shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(4, 4)), false);
var buffer = shape.FindIntersections(new Vector2(0, 10), new Vector2(10, 0)).ToArray();
Vector2[] buffer = shape.FindIntersections(new Vector2(0, 10), new Vector2(10, 0)).ToArray();
Assert.Equal(0, buffer.Length);
}
[Fact]
public void Intersections_Diagonal_and_straight_Hit()
{
var shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(4, 4)), false);
InternalPath shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(4, 4)), false);
var buffer = shape.FindIntersections(new Vector2(3, 10), new Vector2(3, 0)).ToArray();
Vector2[] buffer = shape.FindIntersections(new Vector2(3, 10), new Vector2(3, 0)).ToArray();
Assert.Equal(1, buffer.Length);
Assert.Equal(new Vector2(3, 3), buffer[0]);
@ -220,9 +240,9 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Intersections_Diagonal_and_straight_NoHit()
{
var shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(4, 4)), false);
InternalPath shape = new InternalPath(new LinearLineSegment(new Vector2(0, 0), new Vector2(4, 4)), false);
var buffer = shape.FindIntersections(new Vector2(3, 10), new Vector2(3, 3.5f)).ToArray();
Vector2[] buffer = shape.FindIntersections(new Vector2(3, 10), new Vector2(3, 3.5f)).ToArray();
Assert.Equal(0, buffer.Length);
}

Просмотреть файл

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using Xunit;
namespace SixLabors.Shapes.Tests
{
/// <summary>
/// see https://github.com/SixLabors/Shapes/issues/16
/// Also for furter details see https://github.com/SixLabors/Fonts/issues/22
/// </summary>
public class Issue_16
{
[Fact]
public void IndexOutoufRangeException()
{
InternalPath p = new InternalPath(new[] { new Vector2(0, 0), new Vector2(0.000000001f, 0), new Vector2(0, 0.000000001f) }, true);
IEnumerable<Vector2> inter = p.FindIntersections(Vector2.One, Vector2.Zero);
// if simplified to single point then we should never have an intersection
Assert.Equal(0, inter.Count());
}
}
}

Просмотреть файл

@ -13,8 +13,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void SingleSegmentConstructor()
{
var segment = new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 10));
var flatPath = segment.Flatten();
LinearLineSegment segment = new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 10));
System.Collections.Immutable.ImmutableArray<Vector2> flatPath = segment.Flatten();
Assert.Equal(2, flatPath.Length);
Assert.Equal(new Vector2(0, 0), flatPath[0]);
Assert.Equal(new Vector2(10, 10), flatPath[1]);
@ -23,7 +23,7 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MustHaveAtleast2Points()
{
var error = Assert.Throws<ArgumentOutOfRangeException>(() => new LinearLineSegment(new[] { new Vector2(0, 0) }));
ArgumentOutOfRangeException error = Assert.Throws<ArgumentOutOfRangeException>(() => new LinearLineSegment(new[] { new Vector2(0, 0) }));
}
[Fact]

Просмотреть файл

@ -23,19 +23,23 @@ namespace SixLabors.Shapes
/// <returns>The points along the line the intersect with the boundaries of the polygon.</returns>
internal static IEnumerable<Vector2> FindIntersections(this InternalPath path, Vector2 start, Vector2 end)
{
var buffer = ArrayPool<Vector2>.Shared.Rent(path.PointCount);
List<Vector2> results = new List<Vector2>();
Vector2[] buffer = ArrayPool<Vector2>.Shared.Rent(path.PointCount);
try
{
var hits = path.FindIntersections(start, end, buffer, path.PointCount, 0);
for (var i = 0; i < hits; i++)
int hits = path.FindIntersections(start, end, buffer, path.PointCount, 0);
for (int i = 0; i < hits; i++)
{
yield return buffer[i];
results.Add(buffer[i]);
}
}
finally
{
ArrayPool<Vector2>.Shared.Return(buffer);
}
}
return results;
}
}
}

Просмотреть файл

@ -30,7 +30,7 @@ namespace SixLabors.Shapes.Tests
{
//validate matrix in here
var targetMatrix = Matrix3x2.CreateRotation(angle, bounds.Center);
Matrix3x2 targetMatrix = Matrix3x2.CreateRotation(angle, bounds.Center);
Assert.Equal(targetMatrix, m);
@ -50,9 +50,9 @@ namespace SixLabors.Shapes.Tests
.Callback<Matrix3x2>(m =>
{
//validate matrix in here
var radians = (float)(Math.PI * angle / 180.0);
float radians = (float)(Math.PI * angle / 180.0);
var targetMatrix = Matrix3x2.CreateRotation(radians, bounds.Center);
Matrix3x2 targetMatrix = Matrix3x2.CreateRotation(radians, bounds.Center);
Assert.Equal(targetMatrix, m);
@ -73,7 +73,7 @@ namespace SixLabors.Shapes.Tests
{
//validate matrix in here
var targetMatrix = Matrix3x2.CreateTranslation(point);
Matrix3x2 targetMatrix = Matrix3x2.CreateTranslation(point);
Assert.Equal(targetMatrix, m);
@ -95,7 +95,7 @@ namespace SixLabors.Shapes.Tests
{
//validate matrix in here
var targetMatrix = Matrix3x2.CreateTranslation(new Vector2(x, y));
Matrix3x2 targetMatrix = Matrix3x2.CreateTranslation(new Vector2(x, y));
Assert.Equal(targetMatrix, m);

Просмотреть файл

@ -13,10 +13,10 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Bounds()
{
var seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(2, 2));
var seg2 = new LinearLineSegment(new Vector2(4, 4), new Vector2(5, 5));
LinearLineSegment seg1 = new LinearLineSegment(new Vector2(0, 0), new Vector2(2, 2));
LinearLineSegment seg2 = new LinearLineSegment(new Vector2(4, 4), new Vector2(5, 5));
var path = new Path(seg1, seg2);
Path path = new Path(seg1, seg2);
Assert.Equal(0, path.Bounds.Left);
Assert.Equal(5, path.Bounds.Right);
@ -55,8 +55,8 @@ namespace SixLabors.Shapes.Tests
[MemberData(nameof(PathDistanceTheoryData))]
public void DistanceFromPath_Path(TestPoint point, float expectedDistance, float alongPath)
{
var path = new Path(new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 0), new Vector2(10, 10), new Vector2(0, 10)));
var info = path.Distance(point);
Path path = new Path(new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 0), new Vector2(10, 10), new Vector2(0, 10)));
PointInfo info = path.Distance(point);
Assert.Equal(expectedDistance, info.DistanceFromPath);
Assert.Equal(alongPath, info.DistanceAlongPath);
}
@ -64,8 +64,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void SimplePath()
{
var path = new Path(new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 0), new Vector2(10, 10), new Vector2(0, 10)));
var points = path.Flatten().Single().Points;
Path path = new Path(new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 0), new Vector2(10, 10), new Vector2(0, 10)));
System.Collections.Immutable.ImmutableArray<Vector2> points = path.Flatten().Single().Points;
Assert.Equal(4, points.Length);
Assert.Equal(new Vector2(0, 0), points[0]);

Просмотреть файл

@ -35,12 +35,12 @@ namespace SixLabors.Shapes.Tests.PolygonClipper
private ImmutableArray<IPath> Clip(IPath shape, params IPath[] hole)
{
var clipper = new Clipper();
Clipper clipper = new Clipper();
clipper.AddPath(shape, ClippingType.Subject);
if (hole != null)
{
foreach (var s in hole)
foreach (IPath s in hole)
{
clipper.AddPath(s, ClippingType.Clip);
}
@ -52,11 +52,11 @@ namespace SixLabors.Shapes.Tests.PolygonClipper
[Fact]
public void OverlappingTriangles()
{
var shapes = this.Clip(this.BigTriangle, this.LittleTriangle);
ImmutableArray<IPath> shapes = this.Clip(this.BigTriangle, this.LittleTriangle);
Assert.Equal(1, shapes.Length);
var path = shapes.Single().Flatten()[0].Points;
ImmutableArray<Vector2> path = shapes.Single().Flatten()[0].Points;
Assert.Equal(7, path.Length);
foreach (var p in this.BigTriangle.Flatten()[0].Points)
foreach (Vector2 p in this.BigTriangle.Flatten()[0].Points)
{
Assert.Contains(p, path);
}
@ -65,7 +65,7 @@ namespace SixLabors.Shapes.Tests.PolygonClipper
[Fact]
public void NonOverlapping()
{
var shapes = this.Clip(this.TopLeft, this.TopRight);
ImmutableArray<IPath> shapes = this.Clip(this.TopLeft, this.TopRight);
Assert.Equal(1, shapes.Length);
Assert.Contains(this.TopLeft, shapes);
Assert.DoesNotContain(this.TopRight, shapes);
@ -74,7 +74,7 @@ namespace SixLabors.Shapes.Tests.PolygonClipper
[Fact]
public void OverLappingReturns1NewShape()
{
var shapes = this.Clip(this.BigSquare, this.TopLeft);
ImmutableArray<IPath> shapes = this.Clip(this.BigSquare, this.TopLeft);
Assert.Equal(1, shapes.Length);
Assert.DoesNotContain(this.BigSquare, shapes);
Assert.DoesNotContain(this.TopLeft, shapes);
@ -83,7 +83,7 @@ namespace SixLabors.Shapes.Tests.PolygonClipper
[Fact]
public void OverlappingButNotCrossingRetuensOrigionalShapes()
{
var shapes = this.Clip(this.BigSquare, this.Hole);
ImmutableArray<IPath> shapes = this.Clip(this.BigSquare, this.Hole);
Assert.Equal(2, shapes.Length);
Assert.Contains(this.BigSquare, shapes);
Assert.Contains(this.Hole, shapes);
@ -92,7 +92,7 @@ namespace SixLabors.Shapes.Tests.PolygonClipper
[Fact]
public void TouchingButNotOverlapping()
{
var shapes = this.Clip(this.TopMiddle, this.TopLeft);
ImmutableArray<IPath> shapes = this.Clip(this.TopMiddle, this.TopLeft);
Assert.Equal(1, shapes.Length);
Assert.DoesNotContain(this.TopMiddle, shapes);
Assert.DoesNotContain(this.TopLeft, shapes);
@ -101,9 +101,9 @@ namespace SixLabors.Shapes.Tests.PolygonClipper
[Fact]
public void ClippingRectanglesCreateCorrectNumberOfPoints()
{
var paths = new Rectangle(10, 10, 40, 40).Clip(new Rectangle(20, 0, 20, 20)).Flatten();
ImmutableArray<ISimplePath> paths = new Rectangle(10, 10, 40, 40).Clip(new Rectangle(20, 0, 20, 20)).Flatten();
Assert.Equal(1, paths.Length);
var points = paths[0].Points;
ImmutableArray<Vector2> points = paths[0].Points;
Assert.Equal(8, points.Length);
}

Просмотреть файл

@ -37,7 +37,7 @@ namespace SixLabors.Shapes.Tests
[MemberData(nameof(PointInPolygonTheoryData))]
public void PointInPolygon(TestPoint[] controlPoints, TestPoint point, bool isInside)
{
var shape = new Polygon(new LinearLineSegment(controlPoints.Select(x => (Vector2)x).ToArray()));
Polygon shape = new Polygon(new LinearLineSegment(controlPoints.Select(x => (Vector2)x).ToArray()));
Assert.Equal(isInside, shape.Contains(point));
}
@ -67,7 +67,7 @@ namespace SixLabors.Shapes.Tests
[MemberData(nameof(DistanceTheoryData))]
public void Distance(TestPoint[] controlPoints, TestPoint point, float expected)
{
var shape = new Polygon(new LinearLineSegment(controlPoints.Select(x => (Vector2)x).ToArray()));
Polygon shape = new Polygon(new LinearLineSegment(controlPoints.Select(x => (Vector2)x).ToArray()));
Assert.Equal(expected, shape.Distance(point).DistanceFromPath);
}
@ -103,7 +103,7 @@ namespace SixLabors.Shapes.Tests
public void DistanceFromPath_Path(TestPoint point, float expectedDistance, float alongPath)
{
IPath path = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(10, 0), new Vector2(10, 10), new Vector2(0, 10)));
var info = path.Distance(point);
PointInfo info = path.Distance(point);
Assert.Equal(expectedDistance, info.DistanceFromPath);
Assert.Equal(alongPath, info.DistanceAlongPath);
}
@ -111,8 +111,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void AsSimpleLinearPath()
{
var poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(5, 5)));
var paths = poly.Flatten()[0].Points;
Polygon poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(5, 5)));
System.Collections.Immutable.ImmutableArray<Vector2> paths = poly.Flatten()[0].Points;
Assert.Equal(3, paths.Length);
Assert.Equal(new Vector2(0, 0), paths[0]);
Assert.Equal(new Vector2(0, 10), paths[1]);
@ -122,10 +122,10 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void FindIntersectionsBuffer()
{
var poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(10, 10), new Vector2(10, 0)));
var buffer = new Vector2[2];
Polygon poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(10, 10), new Vector2(10, 0)));
Vector2[] buffer = new Vector2[2];
var hits = poly.FindIntersections(new Vector2(5, -5), new Vector2(5, 15), buffer, 2, 0);
int hits = poly.FindIntersections(new Vector2(5, -5), new Vector2(5, 15), buffer, 2, 0);
Assert.Equal(2, hits);
Assert.Contains(new Vector2(5, 10), buffer);
Assert.Contains(new Vector2(5, 0), buffer);
@ -134,9 +134,9 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void FindIntersectionsCollection()
{
var poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(10, 10), new Vector2(10, 0)));
Polygon poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(10, 10), new Vector2(10, 0)));
var buffer = poly.FindIntersections(new Vector2(5, -5), new Vector2(5, 15)).ToArray();
Vector2[] buffer = poly.FindIntersections(new Vector2(5, -5), new Vector2(5, 15)).ToArray();
Assert.Equal(2, buffer.Length);
Assert.Contains(new Vector2(5, 10), buffer);
Assert.Contains(new Vector2(5, 0), buffer);
@ -145,8 +145,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ReturnsWrapperOfSelfASOwnPath_SingleSegment()
{
var poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(5, 5)));
var paths = poly.Flatten();
Polygon poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(5, 5)));
System.Collections.Immutable.ImmutableArray<ISimplePath> paths = poly.Flatten();
Assert.Equal(1, paths.Length);
Assert.Equal(poly, paths[0]);
}
@ -154,8 +154,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ReturnsWrapperOfSelfASOwnPath_MultiSegment()
{
var poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10)), new LinearLineSegment(new Vector2(2, 5), new Vector2(5, 5)));
var paths = poly.Flatten();
Polygon poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10)), new LinearLineSegment(new Vector2(2, 5), new Vector2(5, 5)));
System.Collections.Immutable.ImmutableArray<ISimplePath> paths = poly.Flatten();
Assert.Equal(1, paths.Length);
Assert.Equal(poly, paths[0]);
}
@ -163,8 +163,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Bounds()
{
var poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(5, 5)));
var bounds = poly.Bounds;
Polygon poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10), new Vector2(5, 5)));
Rectangle bounds = poly.Bounds;
Assert.Equal(0, bounds.Left);
Assert.Equal(0, bounds.Top);
Assert.Equal(5, bounds.Right);
@ -174,7 +174,7 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MaxIntersections()
{
var poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10)));
Polygon poly = new Polygon(new LinearLineSegment(new Vector2(0, 0), new Vector2(0, 10)));
// with linear polygons its the number of points the segments have
Assert.Equal(2, poly.MaxIntersections);
@ -183,30 +183,30 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void FindBothIntersections()
{
var poly = new Polygon(new LinearLineSegment(
Polygon poly = new Polygon(new LinearLineSegment(
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)));
var intersections = poly.FindIntersections(new Vector2(float.MinValue, 55), new Vector2(float.MaxValue, 55));
IEnumerable<Vector2> intersections = poly.FindIntersections(new Vector2(float.MinValue, 55), new Vector2(float.MaxValue, 55));
Assert.Equal(2, intersections.Count());
}
[Fact]
public void HandleClippingInnerCorner()
{
var simplePath = new Polygon(new LinearLineSegment(
Polygon simplePath = new Polygon(new LinearLineSegment(
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)));
var hole1 = new Polygon(new LinearLineSegment(
Polygon hole1 = new Polygon(new LinearLineSegment(
new Vector2(37, 85),
new Vector2(130, 40),
new Vector2(65, 137)));
var poly = simplePath.Clip(hole1);
IPath poly = simplePath.Clip(hole1);
var intersections = poly.FindIntersections(new Vector2(float.MinValue, 137), new Vector2(float.MaxValue, 137));
IEnumerable<Vector2> intersections = poly.FindIntersections(new Vector2(float.MinValue, 137), new Vector2(float.MaxValue, 137));
// returns an even number of points
Assert.Equal(4, intersections.Count());
@ -216,12 +216,12 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void CrossingCorner()
{
var simplePath = new Polygon(new LinearLineSegment(
Polygon simplePath = new Polygon(new LinearLineSegment(
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)));
var intersections = simplePath.FindIntersections(new Vector2(float.MinValue, 150), new Vector2(float.MaxValue, 150));
IEnumerable<Vector2> intersections = simplePath.FindIntersections(new Vector2(float.MinValue, 150), new Vector2(float.MaxValue, 150));
// returns an even number of points
Assert.Equal(2, intersections.Count());
@ -231,9 +231,9 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ClippingEdgefromInside()
{
var simplePath = new Rectangle(10, 10, 100, 100).Clip(new Rectangle(20, 0, 20, 20));
IPath simplePath = new Rectangle(10, 10, 100, 100).Clip(new Rectangle(20, 0, 20, 20));
var intersections = simplePath.FindIntersections(new Vector2(float.MinValue, 20), new Vector2(float.MaxValue, 20));
IEnumerable<Vector2> intersections = simplePath.FindIntersections(new Vector2(float.MinValue, 20), new Vector2(float.MaxValue, 20));
// returns an even number of points
Assert.Equal(4, intersections.Count());
@ -242,12 +242,12 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ClippingEdgeFromOutside()
{
var simplePath = new Polygon(new LinearLineSegment(
Polygon simplePath = new Polygon(new LinearLineSegment(
new Vector2(10, 10),
new Vector2(100, 10),
new Vector2(50, 300)));
var intersections = simplePath.FindIntersections(new Vector2(float.MinValue, 10), new Vector2(float.MaxValue, 10));
IEnumerable<Vector2> intersections = simplePath.FindIntersections(new Vector2(float.MinValue, 10), new Vector2(float.MaxValue, 10));
// returns an even number of points
Assert.Equal(0, intersections.Count() % 2);
@ -256,19 +256,19 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void HandleClippingOutterCorner()
{
var simplePath = new Polygon(new LinearLineSegment(
Polygon simplePath = new Polygon(new LinearLineSegment(
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)));
var hole1 = new Polygon(new LinearLineSegment(
Polygon hole1 = new Polygon(new LinearLineSegment(
new Vector2(37, 85),
new Vector2(130, 40),
new Vector2(65, 137)));
var poly = simplePath.Clip(hole1);
IPath poly = simplePath.Clip(hole1);
var intersections = poly.FindIntersections(new Vector2(float.MinValue, 300), new Vector2(float.MaxValue, 300));
IEnumerable<Vector2> intersections = poly.FindIntersections(new Vector2(float.MinValue, 300), new Vector2(float.MaxValue, 300));
// returns an even number of points
Assert.Equal(2, intersections.Count());
@ -277,19 +277,19 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void MissingIntersection()
{
var simplePath = new Polygon(new LinearLineSegment(
Polygon simplePath = new Polygon(new LinearLineSegment(
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)));
var hole1 = new Polygon(new LinearLineSegment(
Polygon hole1 = new Polygon(new LinearLineSegment(
new Vector2(37, 85),
new Vector2(130, 40),
new Vector2(65, 137)));
var poly = simplePath.Clip(hole1);
IPath poly = simplePath.Clip(hole1);
var intersections = poly.FindIntersections(new Vector2(float.MinValue, 85), new Vector2(float.MaxValue, 85));
IEnumerable<Vector2> intersections = poly.FindIntersections(new Vector2(float.MinValue, 85), new Vector2(float.MaxValue, 85));
// returns an even number of points
Assert.Equal(4, intersections.Count());
@ -309,9 +309,9 @@ namespace SixLabors.Shapes.Tests
new Vector2(300, 400)
};
var poly = new Polygon(new BezierLineSegment(simplePath));
Polygon poly = new Polygon(new BezierLineSegment(simplePath));
var points = poly.FindIntersections(new Vector2(float.MinValue, y), new Vector2(float.MaxValue, y)).ToList();
List<Vector2> points = poly.FindIntersections(new Vector2(float.MinValue, y), new Vector2(float.MaxValue, y)).ToList();
Assert.Equal(2, points.Count());
}

Просмотреть файл

@ -103,7 +103,7 @@ namespace SixLabors.Shapes.Tests
[MemberData(nameof(PointInPolygonTheoryData))]
public void PointInPolygon(TestPoint location, TestSize size, TestPoint point, bool isInside)
{
var shape = new Rectangle(location, size);
Rectangle shape = new Rectangle(location, size);
Assert.Equal(isInside, shape.Contains(point));
}
@ -121,7 +121,7 @@ namespace SixLabors.Shapes.Tests
public void DistanceFromPath_Path(TestPoint point, float expectecDistance, float alongPath)
{
IPath shape = new Rectangle(0, 0, 10, 10).AsPath();
var info = shape.Distance(point);
PointInfo info = shape.Distance(point);
Assert.Equal(expectecDistance, info.DistanceFromPath);
Assert.Equal(alongPath, info.DistanceAlongPath);
}
@ -129,35 +129,35 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Left()
{
var shape = new Rectangle(10, 11, 12, 13);
Rectangle shape = new Rectangle(10, 11, 12, 13);
Assert.Equal(10, shape.Left);
}
[Fact]
public void Right()
{
var shape = new Rectangle(10, 11, 12, 13);
Rectangle shape = new Rectangle(10, 11, 12, 13);
Assert.Equal(22, shape.Right);
}
[Fact]
public void Top()
{
var shape = new Rectangle(10, 11, 12, 13);
Rectangle shape = new Rectangle(10, 11, 12, 13);
Assert.Equal(11, shape.Top);
}
[Fact]
public void Bottom()
{
var shape = new Rectangle(10, 11, 12, 13);
Rectangle shape = new Rectangle(10, 11, 12, 13);
Assert.Equal(24, shape.Bottom);
}
[Fact]
public void Size()
{
var shape = new Rectangle(10, 11, 12, 13);
Rectangle shape = new Rectangle(10, 11, 12, 13);
Assert.Equal(12, shape.Size.Width);
Assert.Equal(13, shape.Size.Height);
}
@ -176,7 +176,7 @@ namespace SixLabors.Shapes.Tests
public void LienearSegements()
{
IPath shape = new Rectangle(10, 11, 12, 13).AsPath();
var segemnts = shape.Flatten()[0].Points;
System.Collections.Immutable.ImmutableArray<Vector2> segemnts = shape.Flatten()[0].Points;
Assert.Equal(new Vector2(10, 11), segemnts[0]);
Assert.Equal(new Vector2(22, 11), segemnts[1]);
Assert.Equal(new Vector2(22, 24), segemnts[2]);
@ -187,7 +187,7 @@ namespace SixLabors.Shapes.Tests
public void Intersections_2()
{
IPath shape = new Rectangle(1, 1, 10, 10);
var intersections = shape.FindIntersections(new Vector2(0, 5), new Vector2(20, 5));
IEnumerable<Vector2> intersections = shape.FindIntersections(new Vector2(0, 5), new Vector2(20, 5));
Assert.Equal(2, intersections.Count());
Assert.Equal(new Vector2(1, 5), intersections.First());
@ -198,7 +198,7 @@ namespace SixLabors.Shapes.Tests
public void Intersections_1()
{
IPath shape = new Rectangle(1, 1, 10, 10);
var intersections = shape.FindIntersections(new Vector2(0, 5), new Vector2(5, 5));
IEnumerable<Vector2> intersections = shape.FindIntersections(new Vector2(0, 5), new Vector2(5, 5));
Assert.Equal(1, intersections.Count());
Assert.Equal(new Vector2(1, 5), intersections.First());
@ -208,7 +208,7 @@ namespace SixLabors.Shapes.Tests
public void Intersections_0()
{
IPath shape = new Rectangle(1, 1, 10, 10);
var intersections = shape.FindIntersections(new Vector2(0, 5), new Vector2(-5, 5));
IEnumerable<Vector2> intersections = shape.FindIntersections(new Vector2(0, 5), new Vector2(-5, 5));
Assert.Equal(0, intersections.Count());
}
@ -243,7 +243,7 @@ namespace SixLabors.Shapes.Tests
{
IPath shape = new Rectangle(0, 0, 200, 60);
var transformdShape = shape.Transform(Matrix3x2.Identity);
IPath transformdShape = shape.Transform(Matrix3x2.Identity);
Assert.Same(shape, transformdShape);
}
@ -253,7 +253,7 @@ namespace SixLabors.Shapes.Tests
{
IPath shape = new Rectangle(0, 0, 200, 60);
var newShape = shape.Transform(new Matrix3x2(0, 1, 1, 0, 20, 2));
IPath newShape = shape.Transform(new Matrix3x2(0, 1, 1, 0, 20, 2));
Assert.Equal(new Vector2(20, 2), newShape.Bounds.Location);
Assert.Equal(new Size(60, 200), newShape.Bounds.Size);
@ -266,5 +266,26 @@ namespace SixLabors.Shapes.Tests
Assert.Equal(new Vector2(150, 80), shape.Center);
}
const float HalfPi = (float)(Math.PI / 2);
const float Pi = (float)(Math.PI);
[Theory]
[InlineData(0, 50, 50, Pi)]
[InlineData(100, 150, 50, Pi)]
[InlineData(200, 250, 50, -HalfPi)]
[InlineData(259, 250, 109, -HalfPi)]
[InlineData(261, 249, 110, 0)]
[InlineData(620, 150, 50, Pi)] // wrap about end of path
public void PointOnPath(float distance, float expectedX, float expectedY, float expectedAngle)
{
IPath shape = new Rectangle(50, 50, 200, 60);
var point = shape.PointAlongPath(distance);
Assert.Equal(expectedX, point.Point.X);
Assert.Equal(expectedY, point.Point.Y);
Assert.Equal(expectedAngle, point.Angle);
}
}
}

Просмотреть файл

@ -21,13 +21,13 @@ namespace SixLabors.Shapes.Tests
{
if (throws)
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new RegularPolygon(Vector2.Zero, points, 10f, 0));
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => new RegularPolygon(Vector2.Zero, points, 10f, 0));
Assert.Equal("verticies", ex.ParamName);
}
else
{
var p = new RegularPolygon(Vector2.Zero, points, 10f, 0);
RegularPolygon p = new RegularPolygon(Vector2.Zero, points, 10f, 0);
Assert.NotNull(p);
}
}
@ -41,13 +41,13 @@ namespace SixLabors.Shapes.Tests
{
if (throws)
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new RegularPolygon(Vector2.Zero, 3, radius, 0));
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => new RegularPolygon(Vector2.Zero, 3, radius, 0));
Assert.Equal("radius", ex.ParamName);
}
else
{
var p = new RegularPolygon(Vector2.Zero, 3, radius, 0);
RegularPolygon p = new RegularPolygon(Vector2.Zero, 3, radius, 0);
Assert.NotNull(p);
}
}
@ -58,23 +58,23 @@ namespace SixLabors.Shapes.Tests
float radius = 10;
int pointsCount = new Random().Next(3, 20);
var poly = new RegularPolygon(Vector2.Zero, pointsCount, radius, 0);
RegularPolygon poly = new RegularPolygon(Vector2.Zero, pointsCount, radius, 0);
var points = poly.Flatten()[0].Points;
System.Collections.Immutable.ImmutableArray<Vector2> points = poly.Flatten()[0].Points;
// calcualte baselineDistance
var baseline = Vector2.Distance(points[0], points[1]);
float baseline = Vector2.Distance(points[0], points[1]);
// all points are extact the same distance away from the center
for (var i = 0; i < points.Length; i++)
for (int i = 0; i < points.Length; i++)
{
var j = i - 1;
int j = i - 1;
if (i == 0)
{
j = points.Length - 1;
}
var actual = Vector2.Distance(points[i], points[j]);
float actual = Vector2.Distance(points[i], points[j]);
Assert.Equal(baseline, actual, 3);
Assert.Equal(radius, Vector2.Distance(Vector2.Zero, points[i]), 3);
}
@ -87,10 +87,10 @@ namespace SixLabors.Shapes.Tests
float radius = 10;
double anAngle = new Random().NextDouble() * TwoPI;
var poly = new RegularPolygon(Vector2.Zero, 3, radius, (float)anAngle);
var points = poly.Flatten()[0].Points;
RegularPolygon poly = new RegularPolygon(Vector2.Zero, 3, radius, (float)anAngle);
System.Collections.Immutable.ImmutableArray<Vector2> points = poly.Flatten()[0].Points;
var allAngles = points.Select(b => Math.Atan2(b.Y, b.X))
IEnumerable<double> allAngles = points.Select(b => Math.Atan2(b.Y, b.X))
.Select(x => x < 0 ? x + TwoPI : x); // normalise it from +/- PI to 0 to TwoPI
Assert.Contains(allAngles, a => Math.Abs(a - anAngle) > 0.000001);
@ -100,8 +100,8 @@ namespace SixLabors.Shapes.Tests
public void TriangleMissingIntersectionsDownCenter()
{
var poly = new SixLabors.Shapes.RegularPolygon(50, 50, 3, 30);
var points = poly.FindIntersections(new Vector2(0, 50), new Vector2(100, 50)).ToArray();
RegularPolygon poly = new SixLabors.Shapes.RegularPolygon(50, 50, 3, 30);
Vector2[] points = poly.FindIntersections(new Vector2(0, 50), new Vector2(100, 50)).ToArray();
Assert.Equal(2, points.Length);
}
@ -109,8 +109,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ClippingCornerShouldReturn2Points()
{
var poly = new RegularPolygon(50, 50, 7, 30, -(float)Math.PI);
var points = poly.FindIntersections(new Vector2(0, 20), new Vector2(100, 20)).ToArray();
RegularPolygon poly = new RegularPolygon(50, 50, 7, 30, -(float)Math.PI);
Vector2[] points = poly.FindIntersections(new Vector2(0, 20), new Vector2(100, 20)).ToArray();
Assert.Equal(2, points.Length);
}

Просмотреть файл

@ -14,40 +14,40 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void DrawLinesClosedFigure()
{
var builder = new PathBuilder();
PathBuilder builder = new PathBuilder();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
builder.CloseFigure();
var shape = Assert.IsType<Polygon>(builder.Build());
Polygon shape = Assert.IsType<Polygon>(builder.Build());
}
[Fact]
public void AddBezier()
{
var builder = new PathBuilder();
PathBuilder builder = new PathBuilder();
builder.AddBezier(new Vector2(10, 10), new Vector2(20, 20), new Vector2(20, 30), new Vector2(10, 40));
var shape = Assert.IsType<Path>(builder.Build());
Path shape = Assert.IsType<Path>(builder.Build());
}
[Fact]
public void DrawLinesOpenFigure()
{
var builder = new PathBuilder();
PathBuilder builder = new PathBuilder();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
var shape = Assert.IsType<Path>(builder.Build());
Path shape = Assert.IsType<Path>(builder.Build());
}
[Fact]
public void DrawLines2OpenFigures()
{
var builder = new PathBuilder();
PathBuilder builder = new PathBuilder();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
@ -55,7 +55,7 @@ namespace SixLabors.Shapes.Tests
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
var shape = Assert.IsType<ComplexPolygon>(builder.Build());
ComplexPolygon shape = Assert.IsType<ComplexPolygon>(builder.Build());
Assert.Equal(2, shape.Paths.Length);
Assert.IsType<Path>(shape.Paths[0]);
Assert.IsType<Path>(shape.Paths[1]);
@ -63,7 +63,7 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void DrawLinesOpenThenClosedFigures()
{
var builder = new PathBuilder();
PathBuilder builder = new PathBuilder();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
@ -71,7 +71,7 @@ namespace SixLabors.Shapes.Tests
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
builder.CloseFigure();
var shape = Assert.IsType<ComplexPolygon>(builder.Build());
ComplexPolygon shape = Assert.IsType<ComplexPolygon>(builder.Build());
Assert.Equal(2, shape.Paths.Length);
Assert.IsType<Path>(shape.Paths[0]);
@ -81,14 +81,14 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void DrawLinesClosedThenOpenFigures()
{
var builder = new PathBuilder();
PathBuilder builder = new PathBuilder();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
builder.CloseFigure();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
var shape = Assert.IsType<ComplexPolygon>(builder.Build());
ComplexPolygon shape = Assert.IsType<ComplexPolygon>(builder.Build());
Assert.Equal(2, shape.Paths.Length);
Assert.IsType<Polygon>(shape.Paths[0]);
@ -98,14 +98,14 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void DrawLinesCloseAllFigures()
{
var builder = new PathBuilder();
PathBuilder builder = new PathBuilder();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
builder.StartFigure();
builder.AddLine(10, 10, 10, 90);
builder.AddLine(10, 90, 50, 50);
var shape = Assert.IsType<ComplexPolygon>(builder.Build());
ComplexPolygon shape = Assert.IsType<ComplexPolygon>(builder.Build());
Assert.Equal(2, shape.Paths.Length);
Assert.IsType<Path>(shape.Paths[0]);
@ -122,53 +122,53 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void EnumerableAddLines()
{
var point1 = new Vector2(10, 10);
var point2 = new Vector2(10, 90);
var point3 = new Vector2(50, 50);
var builder = new PathBuilder();
Vector2 point1 = new Vector2(10, 10);
Vector2 point2 = new Vector2(10, 90);
Vector2 point3 = new Vector2(50, 50);
PathBuilder builder = new PathBuilder();
builder.AddLines(new List<Vector2> { point1, point2, point3});
var shape = Assert.IsType<Path>(builder.Build());
Path shape = Assert.IsType<Path>(builder.Build());
Assert.Equal(10, shape.Bounds.Left);
}
[Fact]
public void MultipleStartFiguresDoesntCreateEmptyPaths()
{
var point1 = new Vector2(10, 10);
var point2 = new Vector2(10, 90);
var point3 = new Vector2(50, 50);
var builder = new PathBuilder();
Vector2 point1 = new Vector2(10, 10);
Vector2 point2 = new Vector2(10, 90);
Vector2 point3 = new Vector2(50, 50);
PathBuilder builder = new PathBuilder();
builder.StartFigure();
builder.StartFigure();
builder.StartFigure();
builder.StartFigure();
builder.AddLines(new List<Vector2> { point1, point2, point3 });
var shape = Assert.IsType<Path>(builder.Build());
Path shape = Assert.IsType<Path>(builder.Build());
}
[Fact]
public void DefaultTransform()
{
var point1 = new Vector2(10, 10);
var point2 = new Vector2(10, 90);
var point3 = new Vector2(50, 50);
var matrix = Matrix3x2.CreateTranslation(new Vector2(5, 5));
var builder = new PathBuilder(matrix);
Vector2 point1 = new Vector2(10, 10);
Vector2 point2 = new Vector2(10, 90);
Vector2 point3 = new Vector2(50, 50);
Matrix3x2 matrix = Matrix3x2.CreateTranslation(new Vector2(5, 5));
PathBuilder builder = new PathBuilder(matrix);
builder.AddLines(point1, point2, point3);
var shape = builder.Build();
IPath shape = builder.Build();
Assert.Equal(15, shape.Bounds.Left);
}
[Fact]
public void SetTransform()
{
var point1 = new Vector2(10, 10);
var point2 = new Vector2(10, 90);
var point3 = new Vector2(50, 50);
var matrix = Matrix3x2.CreateTranslation(new Vector2(100, 100));
var builder = new PathBuilder();
Vector2 point1 = new Vector2(10, 10);
Vector2 point2 = new Vector2(10, 90);
Vector2 point3 = new Vector2(50, 50);
Matrix3x2 matrix = Matrix3x2.CreateTranslation(new Vector2(100, 100));
PathBuilder builder = new PathBuilder();
builder.AddLines(point1, point2, point3);
builder.SetTransform(matrix);
@ -178,7 +178,7 @@ namespace SixLabors.Shapes.Tests
builder.ResetOrigin();
builder.AddLines(point1, point2, point3);
var shape = Assert.IsType<ComplexPolygon>(builder.Build()).Paths;
System.Collections.Immutable.ImmutableArray<IPath> shape = Assert.IsType<ComplexPolygon>(builder.Build()).Paths;
Assert.Equal(10, shape[0].Bounds.Left);
Assert.Equal(110, shape[1].Bounds.Left);
Assert.Equal(10, shape[0].Bounds.Left);
@ -187,18 +187,18 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void SetOriginLeaveMatrix()
{
var point1 = new Vector2(10, 10);
var point2 = new Vector2(10, 90);
var point3 = new Vector2(50, 50);
var origin = new Vector2(-50, -100);
var builder = new PathBuilder(Matrix3x2.CreateScale(10));
Vector2 point1 = new Vector2(10, 10);
Vector2 point2 = new Vector2(10, 90);
Vector2 point3 = new Vector2(50, 50);
Vector2 origin = new Vector2(-50, -100);
PathBuilder builder = new PathBuilder(Matrix3x2.CreateScale(10));
builder.AddLines(point1, point2, point3);
builder.SetOrigin(origin); //new origin is scaled by default transform
builder.StartFigure();
builder.AddLines(point1, point2, point3);
var shape = Assert.IsType<ComplexPolygon>(builder.Build()).Paths;
System.Collections.Immutable.ImmutableArray<IPath> shape = Assert.IsType<ComplexPolygon>(builder.Build()).Paths;
Assert.Equal(100, shape[0].Bounds.Left);
Assert.Equal(-400, shape[1].Bounds.Left);
}

Просмотреть файл

@ -10,9 +10,9 @@ namespace SixLabors.Shapes.Tests
{
public static IPath IrisSegment(int rotationPos)
{
var center = new Vector2(603);
var segmentRotationCenter = new Vector2(301.16968f, 301.16974f);
var segment = new Polygon(new LinearLineSegment(new Vector2(230.54f, 361.0261f), new System.Numerics.Vector2(5.8641942f, 361.46031f)),
Vector2 center = new Vector2(603);
Vector2 segmentRotationCenter = new Vector2(301.16968f, 301.16974f);
IPath segment = new Polygon(new LinearLineSegment(new Vector2(230.54f, 361.0261f), new System.Numerics.Vector2(5.8641942f, 361.46031f)),
new BezierLineSegment(new Vector2(5.8641942f, 361.46031f),
new Vector2(-11.715693f, 259.54052f),
new Vector2(24.441609f, 158.17478f),
@ -27,9 +27,9 @@ namespace SixLabors.Shapes.Tests
float scalingFactor = size / 1206;
var center = new Vector2(603);
var segmentRotationCenter = new Vector2(301.16968f, 301.16974f);
var segment = new Polygon(new LinearLineSegment(new Vector2(230.54f, 361.0261f), new System.Numerics.Vector2(5.8641942f, 361.46031f)),
Vector2 center = new Vector2(603);
Vector2 segmentRotationCenter = new Vector2(301.16968f, 301.16974f);
IPath segment = new Polygon(new LinearLineSegment(new Vector2(230.54f, 361.0261f), new System.Numerics.Vector2(5.8641942f, 361.46031f)),
new BezierLineSegment(new Vector2(5.8641942f, 361.46031f),
new Vector2(-11.715693f, 259.54052f),
new Vector2(24.441609f, 158.17478f),
@ -37,10 +37,10 @@ namespace SixLabors.Shapes.Tests
float angle = rotationPos * ((float)Math.PI / 3);
var rotated = segment.Transform(Matrix3x2.CreateRotation(angle, center));
IPath rotated = segment.Transform(Matrix3x2.CreateRotation(angle, center));
Matrix3x2 scaler = Matrix3x2.CreateScale(scalingFactor, Vector2.Zero);
var scaled = rotated.Transform(scaler);
IPath scaled = rotated.Transform(scaler);
return scaled;
}
@ -49,7 +49,7 @@ namespace SixLabors.Shapes.Tests
public static IPath HourGlass()
{
// center the shape outerRadii + 10 px away from edges
var sb = new PathBuilder();
PathBuilder sb = new PathBuilder();
// overlay rectangle
sb.AddLine(new Vector2(15, 0), new Vector2(25, 0));

Просмотреть файл

@ -11,71 +11,71 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void Addition()
{
var actual = new Size(12, 13) + new Size(8, 7);
Size actual = new Size(12, 13) + new Size(8, 7);
Assert.Equal(new Size(20, 20), actual);
}
[Fact]
public void Subtraction()
{
var actual = new Size(12, 13) - new Size(2, 2);
Size actual = new Size(12, 13) - new Size(2, 2);
Assert.Equal(new Size(10, 11), actual);
}
[Fact]
public void EqualOperator_True()
{
var actual = new Size(12, 13) == new Size(12, 13);
bool actual = new Size(12, 13) == new Size(12, 13);
Assert.True(actual);
}
[Fact]
public void EqualOperator_False()
{
var actual = new Size(12, 13) == new Size(1, 3);
bool actual = new Size(12, 13) == new Size(1, 3);
Assert.False(actual);
}
[Fact]
public void Equal_True()
{
var actual = new Size(12, 13).Equals((object)new Size(12, 13));
bool actual = new Size(12, 13).Equals((object)new Size(12, 13));
Assert.True(actual);
}
[Fact]
public void Equal_False_SameType()
{
var actual = new Size(12, 13).Equals((object)new Size(1, 3));
bool actual = new Size(12, 13).Equals((object)new Size(1, 3));
Assert.False(actual);
}
[Fact]
public void Equal_False_DiffType()
{
var actual = new Size(12, 13).Equals((object)new object());
bool actual = new Size(12, 13).Equals((object)new object());
Assert.False(actual);
}
[Fact]
public void NotEqualOperator_False()
{
var actual = new Size(12, 13) != new Size(12, 13);
bool actual = new Size(12, 13) != new Size(12, 13);
Assert.False(actual);
}
[Fact]
public void NotEqualOperator_True()
{
var actual = new Size(2, 1) != new Size(12, 13);
bool actual = new Size(2, 1) != new Size(12, 13);
Assert.True(actual);
}
[Fact]
public void GetHashCodeTest()
{
var inst1 = new Size(10, 10);
var inst2 = new Size(10, 10);
Size inst1 = new Size(10, 10);
Size inst2 = new Size(10, 10);
Assert.Equal(inst1.GetHashCode(), inst2.GetHashCode());
}
@ -83,7 +83,7 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ToString_Val()
{
var p = new Size(2,3);
Size p = new Size(2,3);
Assert.Equal("Size [ Width=2, Height=3 ]", p.ToString());
}
}

Просмотреть файл

@ -21,13 +21,13 @@ namespace SixLabors.Shapes.Tests
{
if (throws)
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Star(Vector2.Zero, points, 10f, 20f, 0));
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Star(Vector2.Zero, points, 10f, 20f, 0));
Assert.Equal("prongs", ex.ParamName);
}
else
{
var p = new Star(Vector2.Zero, points, 10f, 20f, 0);
Star p = new Star(Vector2.Zero, points, 10f, 20f, 0);
Assert.NotNull(p);
}
}
@ -41,15 +41,15 @@ namespace SixLabors.Shapes.Tests
{
if (throws)
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Star(Vector2.Zero, 3, radius, 20f, 0));
var ex2 = Assert.Throws<ArgumentOutOfRangeException>(() => new Star(Vector2.Zero, 3, 20f, radius, 0));
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => new Star(Vector2.Zero, 3, radius, 20f, 0));
ArgumentOutOfRangeException ex2 = Assert.Throws<ArgumentOutOfRangeException>(() => new Star(Vector2.Zero, 3, 20f, radius, 0));
Assert.Equal("innerRadii", ex.ParamName);
Assert.Equal("outerRadii", ex2.ParamName);
}
else
{
var p = new Star(Vector2.Zero, 3, radius, radius, 0);
Star p = new Star(Vector2.Zero, 3, radius, radius, 0);
Assert.NotNull(p);
}
}
@ -61,24 +61,24 @@ namespace SixLabors.Shapes.Tests
float radius2 = 30;
int pointsCount = new Random().Next(3, 20);
var poly = new Star(Vector2.Zero, pointsCount, radius, radius2, 0);
Star poly = new Star(Vector2.Zero, pointsCount, radius, radius2, 0);
var points = poly.Flatten()[0].Points;
System.Collections.Immutable.ImmutableArray<Vector2> points = poly.Flatten()[0].Points;
// calcualte baselineDistance
var baseline = Vector2.Distance(points[0], points[1]);
float baseline = Vector2.Distance(points[0], points[1]);
// all points are extact the same distance away from the center
Assert.Equal(pointsCount * 2, points.Length);
for (var i = 0; i < points.Length; i++)
for (int i = 0; i < points.Length; i++)
{
var j = i - 1;
int j = i - 1;
if (j < 0)
{
j += points.Length;
}
var actual = Vector2.Distance(points[i], points[j]);
float actual = Vector2.Distance(points[i], points[j]);
Assert.Equal(baseline, actual, 3);
if (i % 2 == 1)
{
@ -99,10 +99,10 @@ namespace SixLabors.Shapes.Tests
float radius2 = 20;
double anAngle = new Random().NextDouble() * TwoPI;
var poly = new Star(Vector2.Zero, 3, radius, radius2, (float)anAngle);
var points = poly.Flatten();
Star poly = new Star(Vector2.Zero, 3, radius, radius2, (float)anAngle);
System.Collections.Immutable.ImmutableArray<ISimplePath> points = poly.Flatten();
var allAngles = points[0].Points.Select(b => Math.Atan2(b.Y, b.X))
IEnumerable<double> allAngles = points[0].Points.Select(b => Math.Atan2(b.Y, b.X))
.Select(x => x < 0 ? x + TwoPI : x); // normalise it from +/- PI to 0 to TwoPI
Assert.Contains(allAngles, a => Math.Abs(a - anAngle) > 0.000001);
@ -112,8 +112,8 @@ namespace SixLabors.Shapes.Tests
public void TriangleMissingIntersectionsDownCenter()
{
var poly = new SixLabors.Shapes.Star(50, 50, 3, 50, 30);
var points = poly.FindIntersections(new Vector2(0, 50), new Vector2(100, 50)).ToArray();
Star poly = new SixLabors.Shapes.Star(50, 50, 3, 50, 30);
Vector2[] points = poly.FindIntersections(new Vector2(0, 50), new Vector2(100, 50)).ToArray();
Assert.Equal(2, points.Length);
}
@ -121,8 +121,8 @@ namespace SixLabors.Shapes.Tests
[Fact]
public void ClippingCornerShouldReturn2Points()
{
var star = new Star(40, 40, 3, 10, 20);
var points = star.FindIntersections(new Vector2(0, 30), new Vector2(100, 30)).ToArray();
Star star = new Star(40, 40, 3, 10, 20);
Vector2[] points = star.FindIntersections(new Vector2(0, 30), new Vector2(100, 30)).ToArray();
Assert.True(points.Length % 2 == 0, "Should have even number of intersection points");
}