private void CreateSwathContext(double V00x, double V00y, double V00z, double V01x, double V01y, double V01z, double V10x, double V10y, double V10z, double V11x, double V11y, double V11z, out SimpleTriangle HeightInterpolator1, out SimpleTriangle HeightInterpolator2, out SimpleTriangle TimeInterpolator1, out SimpleTriangle TimeInterpolator2) { // Create four corner vertices for location of the processing context var V00 = new XYZ(V00x, V00y, V00z); var V01 = new XYZ(V01x, V01y, V01z); var V10 = new XYZ(V10x, V10y, V10z); var V11 = new XYZ(V11x, V11y, V11z); // Create four corner vertices for time of the processing context (with two epochs three seconds apart var T00 = new XYZ(V00x, V00y, new DateTime(2000, 1, 1, 1, 1, 0, 0, DateTimeKind.Utc).ToOADate()); var T01 = new XYZ(V01x, V01y, new DateTime(2000, 1, 1, 1, 1, 0, 0, DateTimeKind.Utc).ToOADate()); var T10 = new XYZ(V10x, V10y, new DateTime(2000, 1, 1, 1, 1, 3, 0, DateTimeKind.Utc).ToOADate()); var T11 = new XYZ(V11x, V11y, new DateTime(2000, 1, 1, 1, 1, 3, 0, DateTimeKind.Utc).ToOADate()); // Create the height and time interpolation triangles HeightInterpolator1 = new SimpleTriangle(V00, V01, V10); HeightInterpolator2 = new SimpleTriangle(V01, V11, V10); TimeInterpolator1 = new SimpleTriangle(T00, T01, T10); TimeInterpolator2 = new SimpleTriangle(T01, T11, T10); }
public abstract bool PerformSwathing(SimpleTriangle HeightInterpolator1, SimpleTriangle HeightInterpolator2, SimpleTriangle TimeInterpolator1, SimpleTriangle TimeInterpolator2, bool HalfPas, PassType passType, MachineSide machineSide);
public void Test_SimpleTriangleTests_IncludesPoint() { SimpleTriangle tri = new SimpleTriangle(new XYZ(0, 0, 0), new XYZ(0, 100, 0), new XYZ(100, 0, 0)); Assert.True(tri.IncludesPoint(1, 1), "Point (1, 1) not included"); Assert.False(tri.IncludesPoint(100, 100), "Point (1, 1) not included"); Assert.False(tri.IncludesPoint(-1, -1), "Point (1, 1) not included"); }
public void Test_SimpleTriangleTests_Creation() { SimpleTriangle tri = new SimpleTriangle(new XYZ(1, 2, 3), new XYZ(4, 5, 6), new XYZ(7, 8, 9)); Assert.True(tri.V1.X == 1 && tri.V1.Y == 2 && tri.V1.Z == 3 && tri.V2.X == 4 && tri.V2.Y == 5 && tri.V2.Z == 6 && tri.V3.X == 7 && tri.V3.Y == 8 && tri.V3.Z == 9, "Simple triangle not created as expected"); }
public void Test_SimpleTriangleTests_InterpolateHeight() { SimpleTriangle tri = new SimpleTriangle(new XYZ(0, 0, 0), new XYZ(0, 100, 0), new XYZ(100, 0, 0)); Assert.Equal(0, tri.InterpolateHeight(1, 1)); SimpleTriangle tri2 = new SimpleTriangle(new XYZ(0, 0, 100), new XYZ(0, 100, 100), new XYZ(100, 0, 100)); Assert.Equal(100, tri2.InterpolateHeight(1, 1)); SimpleTriangle tri3 = new SimpleTriangle(new XYZ(0, 0, 0), new XYZ(0, 100, 100), new XYZ(100, 0, 0)); Assert.Equal(50, tri3.InterpolateHeight(10, 50)); }
public static void GeometryTriangulate(SqlGeometry MultiPoint) { // Retrieve the SRID int srid = (int)MultiPoint.STSrid; // Check valid input if (!(MultiPoint.STGeometryType() == "MULTIPOINT" && MultiPoint.STNumPoints() > 3)) { throw new ArgumentException("Input must be a MultiPoint containing at least three points"); } // Initialise a list of vertices List <SimplePoint> Vertices = new List <SimplePoint>(); // Add all the original supplied points for (int i = 1; i <= MultiPoint.STNumPoints(); i++) { SimplePoint Point = new SimplePoint((double)MultiPoint.STPointN(i).STX, (double)MultiPoint.STPointN(i).STY); // MultiPoints can contain the same point twice, but this messes up Delauney if (!Vertices.Contains(Point)) { Vertices.Add(Point); } } // Important - count the number of points in the array, NOT using STNumPoints of the supplied geometry, as some duplicate points // may have been removed int numPoints = Vertices.Count; // Sort the list so that points sweep from left - right Vertices.Sort(); // Calculate the "supertriangle" that encompasses the pointset SqlGeometry Envelope = MultiPoint.STEnvelope(); // Width double dx = (double)(Envelope.STPointN(2).STX - Envelope.STPointN(1).STX); // Height double dy = (double)(Envelope.STPointN(4).STY - Envelope.STPointN(1).STY); // Maximum dimension double dmax = (dx > dy) ? dx : dy; // Centre double avgx = (double)Envelope.STCentroid().STX; double avgy = (double)Envelope.STCentroid().STY; // Create the points at corners of the supertriangle SimplePoint a = new SimplePoint(avgx - 2 * dmax, avgy - dmax); SimplePoint b = new SimplePoint(avgx + 2 * dmax, avgy - dmax); SimplePoint c = new SimplePoint(avgx, avgy + 2 * dmax); // Add the supertriangle vertices to the end of the vertex array Vertices.Add(a); Vertices.Add(b); Vertices.Add(c); double radius; SimplePoint circumcentre; CalculateCircumcircle(a, b, c, out circumcentre, out radius); // Create a triangle from the vertices SimpleTriangle SuperTriangle = new SimpleTriangle(numPoints, numPoints + 1, numPoints + 2, circumcentre, radius); // Add the supertriangle to the list of triangles List <SimpleTriangle> Triangles = new List <SimpleTriangle>(); Triangles.Add(SuperTriangle); List <SimpleTriangle> CompletedTriangles = new List <SimpleTriangle>(); // Loop through each point for (int i = 0; i < numPoints; i++) { // Initialise the edge buffer List <int[]> Edges = new List <int[]>(); // Loop through each triangle for (int j = Triangles.Count - 1; j >= 0; j--) { // If the point lies within the circumcircle of this triangle if (Distance(Triangles[j].circumcentre, Vertices[i]) < Triangles[j].radius) { // Add the triangle edges to the edge buffer Edges.Add(new int[] { Triangles[j].a, Triangles[j].b }); Edges.Add(new int[] { Triangles[j].b, Triangles[j].c }); Edges.Add(new int[] { Triangles[j].c, Triangles[j].a }); // Remove this triangle from the list Triangles.RemoveAt(j); } // If this triangle is complete else if (Vertices[i].x > Triangles[j].circumcentre.x + Triangles[j].radius) { CompletedTriangles.Add(Triangles[j]); Triangles.RemoveAt(j); } } // Remove duplicate edges for (int j = Edges.Count - 1; j > 0; j--) { for (int k = j - 1; k >= 0; k--) { // Compare if this edge matches in either direction if (Edges[j][0].Equals(Edges[k][1]) && Edges[j][1].Equals(Edges[k][0])) { // Remove both duplicates Edges.RemoveAt(j); Edges.RemoveAt(k); // We've removed an item from lower down the list than where j is now, so update j j--; break; } } } // Create new triangles for the current point for (int j = 0; j < Edges.Count; j++) { CalculateCircumcircle(Vertices[Edges[j][0]], Vertices[Edges[j][1]], Vertices[i], out circumcentre, out radius); SimpleTriangle T = new SimpleTriangle(Edges[j][0], Edges[j][1], i, circumcentre, radius); Triangles.Add(T); } } // We've finished triangulation. Move any remaining triangles onto the completed list CompletedTriangles.AddRange(Triangles); // Define the metadata of the results column SqlMetaData metadata = new SqlMetaData("Triangle", SqlDbType.Udt, typeof(SqlGeometry)); // Create a record based on this metadata SqlDataRecord record = new SqlDataRecord(metadata); // Send the results back to the client SqlContext.Pipe.SendResultsStart(record); foreach (SimpleTriangle Tri in CompletedTriangles) { // Check that this is a triangle formed only from vertices in the original multipoint // i.e. not from the vertices of the supertriangle. if (Tri.a < numPoints && Tri.b < numPoints && Tri.c < numPoints) { SqlGeometry triangle = TriangleFromPoints(Vertices[Tri.a], Vertices[Tri.b], Vertices[Tri.c], srid); record.SetValue(0, triangle); SqlContext.Pipe.SendResultsRow(record); } } SqlContext.Pipe.SendResultsEnd(); }
/// <summary> /// Calculate diagram voronoi from list of points /// </summary> /// <param name="points">list of points</param> /// <returns>list of polygons</returns> public static IList<IGeometry> GeometryVoronoi(List<IPoint> points) { // Check valid input if (points.Count < 3) { throw new ArgumentException("Input must be a MultiPoint containing at least three points"); } // Initialise a list of vertices List<SimplePoint> vertices = new List<SimplePoint>(); // Add all the original supplied points for (int i = 0; i < points.Count; i++) { SimplePoint point = new SimplePoint(points[i].X, points[i].Y); // MultiPoints can contain the same point twice, but this messes up Delaunay if (!vertices.Contains(point)) { vertices.Add(point); } } // Important - count the number of points in the array as some duplicate points // may have been removed int numPoints = vertices.Count; // Check valid input if (numPoints < 3) { throw new ArgumentException("Input must be a list of points containing at least three points"); } // Important! Sort the list so that points sweep from left - right vertices.Sort(); IPointCollection pointCollection = new MultipointClass(); foreach (SimplePoint p in vertices) { pointCollection.AddPoint(new PointClass() { X = p.X, Y = p.Y }); } // Calculate the "supertriangle" that encompasses the pointset IEnvelope envelope = (pointCollection as IGeometry).Envelope; // Width double dx = envelope.Width; // Height double dy = envelope.Height; // Maximum dimension double dmax = (dx > dy) ? dx : dy; // Centre double avgx = ((envelope.XMax - envelope.XMin) / 2) + envelope.XMin; double avgy = ((envelope.YMax - envelope.YMin) / 2) + envelope.YMin; // Create the points at corners of the supertriangle SimplePoint a = new SimplePoint(avgx - (2 * dmax), avgy - dmax); SimplePoint b = new SimplePoint(avgx + (2 * dmax), avgy - dmax); SimplePoint c = new SimplePoint(avgx, avgy + (2 * dmax)); // Add the supertriangle vertices to the end of the vertex array vertices.Add(a); vertices.Add(b); vertices.Add(c); double radius; SimplePoint circumcentre; Triangulation.CalculateCircumcircle(a, b, c, out circumcentre, out radius); // Create a triangle from the vertices SimpleTriangle superTriangle = new SimpleTriangle(numPoints, numPoints + 1, numPoints + 2, circumcentre, radius); // Add the supertriangle to the list of triangles List<SimpleTriangle> triangles = new List<SimpleTriangle>(); triangles.Add(superTriangle); List<SimpleTriangle> completedTriangles = new List<SimpleTriangle>(); // Loop through each point for (int i = 0; i < numPoints; i++) { // Initialise the edge buffer List<int[]> edges = new List<int[]>(); // Loop through each triangle for (int j = triangles.Count - 1; j >= 0; j--) { // If the point lies within the circumcircle of this triangle if (Distance(triangles[j].CircumCentre, vertices[i]) < triangles[j].Radius) { // Add the triangle edges to the edge buffer edges.Add(new int[] { triangles[j].A, triangles[j].B }); edges.Add(new int[] { triangles[j].B, triangles[j].C }); edges.Add(new int[] { triangles[j].C, triangles[j].A }); // Remove this triangle from the list triangles.RemoveAt(j); } else if (vertices[i].X > triangles[j].CircumCentre.X + triangles[j].Radius) { // If this triangle is complete { completedTriangles.Add(triangles[j]); } triangles.RemoveAt(j); } } // Remove duplicate edges for (int j = edges.Count - 1; j > 0; j--) { for (int k = j - 1; k >= 0; k--) { // Compare if this edge match in either direction if (edges[j][0].Equals(edges[k][1]) && edges[j][1].Equals(edges[k][0])) { // Remove both duplicates edges.RemoveAt(j); edges.RemoveAt(k); // We've removed an item from lower down the list than where j is now, so update j j--; break; } } } // Create new triangles for the current point for (int j = 0; j < edges.Count; j++) { Triangulation.CalculateCircumcircle(vertices[edges[j][0]], vertices[edges[j][1]], vertices[i], out circumcentre, out radius); SimpleTriangle t = new SimpleTriangle(edges[j][0], edges[j][1], i, circumcentre, radius); triangles.Add(t); } } // We've finished triangulation. Move any remaining triangles onto the completed list completedTriangles.AddRange(triangles); IList<IGeometry> voronoiPolygon = new List<IGeometry>(); for (var i = 0; i < vertices.Count; i++) { // Initiliase a new geometry to hold the voronoi polygon IPointCollection mp = new MultipointClass(); // Look through each triangle foreach (SimpleTriangle tri in completedTriangles) { // If the triangle intersects this point if (tri.A == i || tri.B == i || tri.C == i) { mp.AddPoint(new PointClass() { X = tri.CircumCentre.X, Y = tri.CircumCentre.Y }); } } // Create the voronoi polygon from the convex hull of the circumcentres of intersecting triangles ITopologicalOperator topologicalOperator = mp as ITopologicalOperator; IGeometry polygon = topologicalOperator.ConvexHull(); topologicalOperator = polygon as ITopologicalOperator; IGeometry result = topologicalOperator.Intersect(envelope, esriGeometryDimension.esriGeometry2Dimension); if ((result != null) && (!result.IsEmpty)) { voronoiPolygon.Add(result); } } return voronoiPolygon; }
/// <summary> /// 根据输入的一系列点计算voronoi图 /// </summary> /// <param name="points">一系列点</param> /// <returns>一系列多变形</returns> public static IList <IGeometry> GeometryVoronoi(List <IPoint> points) { // 判断点的数量是否合法 if (points.Count < 3) { throw new ArgumentException("Input must be a MultiPoint containing at least three points"); } // 初始化顶点列表 List <SimplePoint> vertices = new List <SimplePoint>(); // 加入所有初始提供的点 for (int i = 0; i < points.Count; i++) { SimplePoint point = new SimplePoint(points[i].X, points[i].Y); // 除掉所有的多点,因为三角剖分算法不支持多点的引入 if (!vertices.Contains(point)) { vertices.Add(point); } } // 计算点集的数量,此时应该已经除掉了所有的重复点 int numPoints = vertices.Count; // 判断点的数量是否合法 if (numPoints < 3) { throw new ArgumentException("Input must be a list of points containing at least three points"); } // 基于vertices中的顶点x坐标对indices进行sort vertices.Sort(); IPointCollection pointCollection = new MultipointClass(); foreach (SimplePoint p in vertices) { pointCollection.AddPoint(new PointClass() { X = p.X, Y = p.Y }); } IEnvelope envelope = (pointCollection as IGeometry).Envelope; // Width double dx = envelope.Width; // Height double dy = envelope.Height; // Maximum dimension double dmax = (dx > dy) ? dx : dy; // Centre double avgx = ((envelope.XMax - envelope.XMin) / 2) + envelope.XMin; double avgy = ((envelope.YMax - envelope.YMin) / 2) + envelope.YMin; // Create the points at corners of the supertriangle SimplePoint a = new SimplePoint(avgx - (2 * dmax), avgy - dmax); SimplePoint b = new SimplePoint(avgx + (2 * dmax), avgy - dmax); SimplePoint c = new SimplePoint(avgx, avgy + (2 * dmax)); // Add the supertriangle vertices to the end of the vertex array vertices.Add(a); vertices.Add(b); vertices.Add(c); double radius; SimplePoint circumcentre; Triangulation.CalculateCircumcircle(a, b, c, out circumcentre, out radius); // 确定超级三角形,这个三角形应该包含所有点 SimpleTriangle superTriangle = new SimpleTriangle(numPoints, numPoints + 1, numPoints + 2, circumcentre, radius); // 将超级三角形push到triangles列表 List <SimpleTriangle> triangles = new List <SimpleTriangle>(); triangles.Add(superTriangle); List <SimpleTriangle> completedTriangles = new List <SimpleTriangle>(); // 遍历基于indecies顺序的vertices中的每一个点 for (int i = 0; i < numPoints; i++) { // 初始化边缓存数组 List <int[]> edges = new List <int[]>(); // 遍历temp triangles中的每一个三角形 for (int j = triangles.Count - 1; j >= 0; j--) { // 如果该点在外接圆内 if (Distance(triangles[j].CircumCentre, vertices[i]) < triangles[j].Radius) { // 则该三角形不为Delaunay三角形,将三边保存至edge buffer edges.Add(new int[] { triangles[j].A, triangles[j].B }); edges.Add(new int[] { triangles[j].B, triangles[j].C }); edges.Add(new int[] { triangles[j].C, triangles[j].A }); // 在temp中除掉该三角形 triangles.RemoveAt(j); } else if (vertices[i].X > triangles[j].CircumCentre.X + triangles[j].Radius) { { completedTriangles.Add(triangles[j]); } triangles.RemoveAt(j); } } // 对edgebuffer进行去重 for (int j = edges.Count - 1; j > 0; j--) { for (int k = j - 1; k >= 0; k--) { // Compare if this edge match in either direction if (edges[j][0].Equals(edges[k][1]) && edges[j][1].Equals(edges[k][0])) { // 去重 edges.RemoveAt(j); edges.RemoveAt(k); // We've removed an item from lower down the list than where j is now, so update j j--; break; } } } // Create new triangles for the current point for (int j = 0; j < edges.Count; j++) { Triangulation.CalculateCircumcircle(vertices[edges[j][0]], vertices[edges[j][1]], vertices[i], out circumcentre, out radius); SimpleTriangle t = new SimpleTriangle(edges[j][0], edges[j][1], i, circumcentre, radius); triangles.Add(t); } } // 我们已经完成了三角剖分部分,接下来就是要完成构建voronoi图的过程 completedTriangles.AddRange(triangles); IList <IGeometry> voronoiPolygon = new List <IGeometry>(); for (var i = 0; i < vertices.Count; i++) { // 新建一个IGeometry来存放voronoi图 IPointCollection mp = new MultipointClass(); // 遍历所有三角形 foreach (SimpleTriangle tri in completedTriangles) { // If the triangle intersects this point if (tri.A == i || tri.B == i || tri.C == i) { mp.AddPoint(new PointClass() { X = tri.CircumCentre.X, Y = tri.CircumCentre.Y }); } } // Create the voronoi polygon from the convex hull of the circumcentres of intersecting triangles ITopologicalOperator topologicalOperator = mp as ITopologicalOperator; IGeometry polygon = topologicalOperator.ConvexHull(); topologicalOperator = polygon as ITopologicalOperator; IGeometry result = topologicalOperator.Intersect(envelope, esriGeometryDimension.esriGeometry2Dimension); if ((result != null) && (!result.IsEmpty)) { voronoiPolygon.Add(result); } } return(voronoiPolygon); }
/// <summary> /// Constructs all the state necessary to describe an interpolation epoch /// </summary> private void ConstructInterpolationState() { // Construct the processing state used to calculate interpolated values //------------ FRONT AXLE ---------------- FrontLeftInterpolationFence = new Fence(); FrontLeftInterpolationFence.SetRectangleFence(0, 0, 1, 1); FrontLeftInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals FrontRightInterpolationFence = new Fence(); FrontRightInterpolationFence.SetRectangleFence(0, 0, 1, 1); FrontRightInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals for (int I = 0; I < 4; I++) { FrontHeights[I] = new XYZ(0, 0, 0); FrontTimes[I] = new XYZ(0, 0, 0); } FrontHeightInterpolator1 = new SimpleTriangle(FrontHeights[0], FrontHeights[1], FrontHeights[2]); FrontHeightInterpolator2 = new SimpleTriangle(FrontHeights[1], FrontHeights[2], FrontHeights[3]); FrontTimeInterpolator1 = new SimpleTriangle(FrontTimes[0], FrontTimes[1], FrontTimes[2]); FrontTimeInterpolator2 = new SimpleTriangle(FrontTimes[1], FrontTimes[2], FrontTimes[3]); //------------ REAR AXLE ---------------- RearLeftInterpolationFence = new Fence(); RearLeftInterpolationFence.SetRectangleFence(0, 0, 1, 1); RearLeftInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals RearRightInterpolationFence = new Fence(); RearRightInterpolationFence.SetRectangleFence(0, 0, 1, 1); RearRightInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals for (int I = 0; I < 4; I++) { RearHeights[I] = new XYZ(0, 0, 0); RearTimes[I] = new XYZ(0, 0, 0); } RearHeightInterpolator1 = new SimpleTriangle(RearHeights[0], RearHeights[1], RearHeights[2]); RearHeightInterpolator2 = new SimpleTriangle(RearHeights[1], RearHeights[2], RearHeights[3]); RearTimeInterpolator1 = new SimpleTriangle(RearTimes[0], RearTimes[1], RearTimes[2]); RearTimeInterpolator2 = new SimpleTriangle(RearTimes[1], RearTimes[2], RearTimes[3]); //------------ Track ---------------- TrackLeftInterpolationFence = new Fence(); TrackLeftInterpolationFence.SetRectangleFence(0, 0, 1, 1); TrackLeftInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals TrackRightInterpolationFence = new Fence(); TrackRightInterpolationFence.SetRectangleFence(0, 0, 1, 1); TrackRightInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals for (int I = 0; I < 4; I++) { TrackHeights[I] = new XYZ(0, 0, 0); TrackTimes[I] = new XYZ(0, 0, 0); } TrackHeightInterpolator1 = new SimpleTriangle(TrackHeights[0], TrackHeights[1], TrackHeights[2]); TrackHeightInterpolator2 = new SimpleTriangle(TrackHeights[1], TrackHeights[2], TrackHeights[3]); TrackTimeInterpolator1 = new SimpleTriangle(TrackTimes[0], TrackTimes[1], TrackTimes[2]); TrackTimeInterpolator2 = new SimpleTriangle(TrackTimes[1], TrackTimes[2], TrackTimes[3]); //------------ Wheel ---------------- WheelLeftInterpolationFence = new Fence(); WheelLeftInterpolationFence.SetRectangleFence(0, 0, 1, 1); WheelLeftInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals WheelRightInterpolationFence = new Fence(); WheelRightInterpolationFence.SetRectangleFence(0, 0, 1, 1); WheelRightInterpolationFence.IsRectangle = false; // Remove rectangle flag as usage context is arbitrary quadrilaterals for (int I = 0; I < 4; I++) { WheelHeights[I] = new XYZ(0, 0, 0); WheelTimes[I] = new XYZ(0, 0, 0); } WheelHeightInterpolator1 = new SimpleTriangle(WheelHeights[0], WheelHeights[1], WheelHeights[2]); WheelHeightInterpolator2 = new SimpleTriangle(WheelHeights[1], WheelHeights[2], WheelHeights[3]); WheelTimeInterpolator1 = new SimpleTriangle(WheelTimes[0], WheelTimes[1], WheelTimes[2]); WheelTimeInterpolator2 = new SimpleTriangle(WheelTimes[1], WheelTimes[2], WheelTimes[3]); InterpolationFences = Enumerable.Range(1, NumFencesToCreate).Select(x => new List <Fence>()).ToArray(); }
public void Test_SimpleTriangleTests_Area() { SimpleTriangle tri = new SimpleTriangle(new XYZ(0, 0, 0), new XYZ(0, 100, 0), new XYZ(100, 0, 0)); Assert.Equal(5000, tri.Area); }