// Calculate the distance between two SimplePoints private static double Distance(SimplePoint p1, SimplePoint p2) { double result = 0; result = Math.Sqrt(Math.Pow((p2.x - p1.x), 2) + Math.Pow((p2.y - p1.y), 2)); return(result); }
public void TwoSimplePointsWithTheSameCoordinatesShouldBeConsideredTheSame() { var simplePoint1 = new SimplePoint(10, 10); var simplePoint2 = new SimplePoint(10, 10); simplePoint1.Equals(simplePoint2).Should().Be(true); }
public void SimplePoint_ConstructorTakingTwoDoubles_InitializeCoordinatesAccordingly() { var simplePoint = new SimplePoint(1.1, 2.2); Assert.Equal(1.1, simplePoint.X); Assert.Equal(2.2, simplePoint.Y); }
/// <summary> /// Calculate the distance between two SimplePoints /// </summary> /// <param name="p1">first point</param> /// <param name="p2">second point</param> /// <returns>distance between two points</returns> private static double Distance(SimplePoint p1, SimplePoint p2) { double result = 0; result = Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2)); return(result); }
//Compute the distance from AB to C //if isSegment is true, AB is a segment, not a line. private static double LineToPointDistance2D(SimplePoint linePoint1, SimplePoint linePoint2, SimplePoint pointTest, bool isSegment = true) { if (linePoint1.X == linePoint1.X && linePoint1.Y == linePoint2.Y) { return(255); } var pointA = new double[] { linePoint1.X, linePoint1.Y }; var pointB = new double[] { linePoint2.X, linePoint2.Y }; var pointC = new double[] { pointTest.X, pointTest.Y }; double dist = CrossProduct(pointA, pointB, pointC) / Distance(pointA, pointB); if (isSegment) { double dot1 = DotProduct(pointA, pointB, pointC); if (dot1 > 0) { return(Distance(pointB, pointC)); } double dot2 = DotProduct(pointB, pointA, pointC); if (dot2 > 0) { return(Distance(pointA, pointC)); } } return(Math.Abs(dist)); }
public void SimplePoint_ParameterlessConstructor_InitializeZeroCoordinates() { var simplePoint = new SimplePoint(); Assert.Equal(0, simplePoint.X); Assert.Equal(0, simplePoint.Y); }
/// <summary> /// calculate center of circle and radius using three points /// </summary> /// <param name="p1">first point</param> /// <param name="p2">second point</param> /// <param name="p3">third point</param> /// <param name="circumCentre">center of circle</param> /// <param name="radius">value of radius</param> private static void CalculateCircumcircle(SimplePoint p1, SimplePoint p2, SimplePoint p3, out SimplePoint circumCentre, out double radius) { // Calculate the length of each side of the triangle double a = Distance(p2, p3); // side a is opposite point 1 double b = Distance(p1, p3); // side b is opposite point 2 double c = Distance(p1, p2); // side c is opposite point 3 // Calculate the radius of the circumcircle double area = Math.Abs(((double)((p1.X * (p2.Y - p3.Y)) + (p2.X * (p3.Y - p1.Y)) + (p3.X * (p1.Y - p2.Y)))) / 2); radius = a * b * c / (4 * area); // Define area coordinates to calculate the circumcentre double pp1 = Math.Pow(a, 2) * (Math.Pow(b, 2) + Math.Pow(c, 2) - Math.Pow(a, 2)); double pp2 = Math.Pow(b, 2) * (Math.Pow(c, 2) + Math.Pow(a, 2) - Math.Pow(b, 2)); double pp3 = Math.Pow(c, 2) * (Math.Pow(a, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)); // Normalise double t1 = pp1 / (pp1 + pp2 + pp3); double t2 = pp2 / (pp1 + pp2 + pp3); double t3 = pp3 / (pp1 + pp2 + pp3); // Convert to Cartesian double x = (t1 * p1.X) + (t2 * p2.X) + (t3 * p3.X); double y = (t1 * p1.Y) + (t2 * p2.Y) + (t3 * p3.Y); circumCentre = new SimplePoint(x, y); }
private static void CalculateCircumcircle(SimplePoint p1, SimplePoint p2, SimplePoint p3, out SimplePoint circumCentre, out double radius) { // Calculate the length of each side of the triangle double a = Distance(p2, p3); // side a is opposite point 1 double b = Distance(p1, p3); // side b is opposite point 2 double c = Distance(p1, p2); // side c is opposite point 3 // Calculate the radius of the circumcircle double area = Math.Abs((double)(p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) / 2); radius = a * b * c / (4 * area); // Define area coordinates to calculate the circumcentre double pp1 = Math.Pow(a, 2) * (Math.Pow(b, 2) + Math.Pow(c, 2) - Math.Pow(a, 2)); double pp2 = Math.Pow(b, 2) * (Math.Pow(c, 2) + Math.Pow(a, 2) - Math.Pow(b, 2)); double pp3 = Math.Pow(c, 2) * (Math.Pow(a, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)); // Normalise double t1 = pp1 / (pp1 + pp2 + pp3); double t2 = pp2 / (pp1 + pp2 + pp3); double t3 = pp3 / (pp1 + pp2 + pp3); // Convert to Cartesian double x = t1 * p1.x + t2 * p2.x + t3 * p3.x; double y = t1 * p1.y + t2 * p2.y + t3 * p3.y; circumCentre = new SimplePoint(x, y); }
protected void SetCenterMap(SimplePoint centerMap, bool animate) { // Take the point that we want to show, and center it on the client's UI. this.BeginInvoke(new Action(() => { // The point that came in is raw on the map... var x = centerMap.X; var y = centerMap.Y; // We also need to account for the client's zoom factor (gives us the X/Y of a Zoomed map), to which we then "unzoom" the X/Y back to the raw map location for scroll purposes. x = (int)(((x * AssignedZoomFactor) - (this.VisibleSize.Width / 2.0d)) * this.InverseZoomFactor); y = (int)(((y * AssignedZoomFactor) - (this.VisibleSize.Height / 2.0d)) * this.InverseZoomFactor); if (!animate) { SetScroll(x, y); return; } // If we're already doing a Center Map fade, we're going to simply pop out the old values. It may glitch a bit to the end user, but the end result will be fine. // Our timer will go from True/0.0 to True/1.0, then flip to False/1.0 down to False/0.0 this.centerMapFadingTimer.Tag = new SimplePoint(x, y); this.centerMapFadingValues = new Tuple <bool, float>(true, 0.0f); this.centerMapFadingTimer.Start(); })); }
/// <summary> /// Initializes a new instance of the <see cref="SimpleTriangle"/> struct /// </summary> /// <param name="a">index vertex a</param> /// <param name="b">index vertex b</param> /// <param name="c">index vertex c</param> /// <param name="circumcentre">center of triangle</param> /// <param name="radius">radius of triangle</param> public SimpleTriangle(int a, int b, int c, SimplePoint circumcentre, double radius) { this.A = a; this.B = b; this.C = c; this.CircumCentre = circumcentre; this.Radius = radius; }
public SimpleTriangle(int a, int b, int c, SimplePoint circumcentre, double radius) { this.a = a; this.b = b; this.c = c; this.circumcentre = circumcentre; this.radius = radius; }
void DrawConectionLines(SimplePoint leftop, SimplePoint rightop) { EndGatePoint = new SimplePoint { X = PortX, Y = PortY }; var x2Input = PortX + 7; var y2Input = PortY + 20; var y22Input = PortY + 40; Polyline leftPolyline = new Polyline(); leftPolyline.Stroke = Brushes.OrangeRed; PointCollection leftpoints = new PointCollection(); leftpoints.Add(new Point { X = leftop.X - 2, Y = leftop.Y }); leftpoints.Add(new Point { X = (x2Input + leftop.X) / 2.2, Y = leftop.Y }); leftpoints.Add(new Point { X = (x2Input + leftop.X) / 2.2, Y = y2Input }); leftpoints.Add(new Point { X = x2Input, Y = y2Input }); leftPolyline.Points = leftpoints; Polyline rightPolyline = new Polyline(); rightPolyline.Stroke = Brushes.OrangeRed; PointCollection rightpoints = new PointCollection(); rightpoints.Add(new Point { X = rightop.X, Y = rightop.Y }); rightpoints.Add(new Point { X = (x2Input + rightop.X) / 2.2 - 5, Y = rightop.Y }); rightpoints.Add(new Point { X = (x2Input + rightop.X) / 2.2 - 5, Y = y22Input }); rightpoints.Add(new Point { X = x2Input, Y = y22Input }); rightPolyline.Points = rightpoints; CircuitField.Children.Add(leftPolyline); CircuitField.Children.Add(rightPolyline); }
private static void SwapPoints(ref SimplePoint sp1, ref SimplePoint sp2) { sp1.X = 100; sp1.Y = 100; SimplePoint temp = sp1; sp1 = sp2; sp2 = temp; }
public static void GeometryTriangulate(SqlGeometry MultiPoint) { List <SimplePoint> Vertices = new List <SimplePoint>(); // Loop through supplied points for (int i = 1; i <= MultiPoint.STNumPoints(); i++) { //Create a new simple point corresponding to this element of the MultiPoint SimplePoint Point = new SimplePoint( (double)MultiPoint.STPointN(i).STX, (double)MultiPoint.STPointN(i).STY ); //Check whether this this point already exists if (!Vertices.Contains(Point)) { Vertices.Add(Point); } } Vertices.Sort(); //Creating the Supertriangle 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); // max dimension double dmax = (dx > dy) ? dx : dy; //Centre SqlGeometry centroid = Envelope.STCentroid(); double avgx = (double)centroid.STX; double avgy = (double)centroid.STY; 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 to the end of the vertex array Vertices.Add(a); Vertices.Add(b); Vertices.Add(c); //create the supertringle double radius; SimplePoint circumcentre; CalculateCircumcircle(a, b, c, out circumcentre, out radius); /////SimpleTriangle SuperTriangle = new SimpleTriangle(numPoints, numPoints + 1, numPoints + 2, circumcentre, radius); //Add the supertriangle List <SimpleTriangle> Triangles = new List <SimpleTriangle>(); //////Triangles.Add(SimpleTriangle); //Create an empty list to hold completed triangles List <SimpleTriangle> CompletedTriangle = new List <SimpleTriangle>(); }
public void ShouldCreateASimplePointSucessfullyWithValidParameters() { var simplePoint = new SimplePoint(10, 10); simplePoint.Should().Not.Be.Null(); simplePoint.GetType().Should().Be <SimplePoint>(); simplePoint.X.Should().Be(10); simplePoint.Y.Should().Be(10); }
public void WriteCenterMap(SimplePoint point) { if (ClientsCount == 0) { return; } EnqueueWrite(new CenterMapSocketObject(point)); }
public IEnumerable <BranchDto> QueryBranchesByCenterPoint(SimplePoint center, double buffer) { return(InAUnitOfWork(session => { var geoLocator = new GeoLocator(session); var geoPoint = _mappingEngine.Map <SimplePoint, Point>(center); var results = geoLocator.Locate <Branch>(geoPoint, buffer); return results.Select(r => _mappingEngine.Map <Branch, BranchDto>(r)).ToList(); })); }
public async Task <ICollection <CrowdsourcedPlace> > GetClosePlaces(SimplePoint start, SimplePoint end) { var query = new SpatialViewQuery().From("doc", "crowdsourcedpoints") .Stale(StaleState.False) .StartRange(start.Longitude, start.Latitude) .EndRange(end.Longitude, end.Latitude); var result = await _bucket.QueryAsync <CrowdsourcedPlace>(query); return(result.Rows.Select(x => x.Value).ToList()); }
public async Task <IEnumerable <CrowdsourcedPlace> > Get( [FromQuery] double leftBottomX, [FromQuery] double leftBottomY, [FromQuery] double rightTopX, [FromQuery] double rightTopY) { var leftBottom = new SimplePoint(leftBottomX, leftBottomY); var rightTop = new SimplePoint(rightTopX, rightTopY); return(await _crowdsourcedPlacesService.GetClosePlaces(leftBottom, rightTop)); }
public void ShouldCreateAProperArrayWithCoordinates() { var simplePoint = new SimplePoint(15, 30); var simplePointArray = simplePoint.ToArray(); simplePointArray.Should().Not.Be.Null(); simplePointArray.Length.Should().Be(2); simplePointArray[0].Should().Be(15); simplePointArray[1].Should().Be(30); }
public void IsTheSame_ProvidingDifferentPoints_ReturnsFalse() { //Arrange SimplePoint simplePoint1 = new SimplePoint(0, 0); SimplePoint simplePoint2 = new SimplePoint(10, 10); //Act var result = simplePoint1.IsTheSame(simplePoint2, 3); //Assert Assert.False(result); }
public void IsTheSame_ProvidingTheSamePoints_ReturnsTrue() { //Arrange SimplePoint simplePoint1 = new SimplePoint(0, 0); SimplePoint simplePoint2 = new SimplePoint(0, 0); //Act var result = simplePoint1.IsTheSame(simplePoint2, 3); //Assert Assert.True(result); }
public void Distance_InsertSimplePoint_ReturnsDistanceToSimplePoint() { //Arrange SimplePoint simplePoint1 = new SimplePoint(0, 0); SimplePoint simplePoint2 = new SimplePoint(1, 1); var expectedResult = Math.Sqrt(2); //Act var result = simplePoint1.Distance(simplePoint2); //Assert Assert.True((bool)(Math.Abs(result - expectedResult) < Double.Epsilon)); }
static void Main(string[] args) { //CustomConsoleExample(); var encoded = GetCodePoint('S'); BinaryFormatterTest.Test(); Console.ReadKey(); ActivityHandler activityHandler = new ActivityHandler(); activityHandler.WriteActivityStateInternal(); activityHandler.ReadActivityState(); Console.ReadKey(); int intVal1 = 1; int intVal2 = 2; Console.WriteLine("Integers before regular swap method: {0} & {1}", intVal1, intVal2); SwapIntegers(intVal1, intVal2); Console.WriteLine("Integers after regular swap method: {0} & {1}", intVal1, intVal2); SwapIntegersByRef(ref intVal1, ref intVal2); Console.WriteLine("Integers after ref swap method: {0} & {1}", intVal1, intVal2); Console.ReadKey(); PrintRedLine(); SimplePoint sp1 = new SimplePoint(); SimplePoint sp2 = new SimplePoint(); Console.WriteLine("Points before swap method: {0} & {1}", sp1, sp2); SwapPoints(sp1, sp2); Console.WriteLine("Points after swap method: {0} & {1}", sp1, sp2); SwapPoints(ref sp1, ref sp2); Console.WriteLine("Points after ref swap method: {0} & {1}", sp1, sp2); PrintRedLine(); Type intListType = typeof(List <int>); Type stringListType = typeof(List <string>); Console.WriteLine("intList type = " + intListType.ToString()); Console.WriteLine("stringList type = " + stringListType.FullName); Console.WriteLine(); Console.WriteLine("Press any key to quit..."); Console.ReadKey(); }
// Construct a triangle from 3 vertices private static SqlGeometry TriangleFromPoints(SimplePoint p1, SimplePoint p2, SimplePoint p3, int srid) { SqlGeometryBuilder TriangleBuilder = new SqlGeometryBuilder(); TriangleBuilder.SetSrid(srid); TriangleBuilder.BeginGeometry(OpenGisGeometryType.Polygon); TriangleBuilder.BeginFigure(p1.x, p1.y); TriangleBuilder.AddLine(p2.x, p2.y); TriangleBuilder.AddLine(p3.x, p3.y); TriangleBuilder.AddLine(p1.x, p1.y); TriangleBuilder.EndFigure(); TriangleBuilder.EndGeometry(); return(TriangleBuilder.ConstructedGeometry); }
/// <summary> /// Implement IComparable CompareTo method to enable sorting /// </summary> /// <param name="obj">object simple point</param> /// <returns>value of compare</returns> int IComparable.CompareTo(object obj) { SimplePoint other = (SimplePoint)obj; if (this.X > other.X) { return(1); } else if (this.X < other.X) { return(-1); } else { return(0); } }
public SimplePoint DrawAndPort(SimplePoint leftop, SimplePoint rightop) { ANDControl andControl = new ANDControl(); Canvas.SetLeft(andControl, PortX); Canvas.SetTop(andControl, PortY); CircuitField.Children.Add(andControl); DrawConectionLines(leftop, rightop); var con = new SimplePoint { X = PortX + LogicGateWidth, Y = PortY + LogicGateHeight / 2 }; IncrementGatesCordinate(); return(con); }
public SimplePoint DrawNotPort(SimplePoint expPoint) { NotControl notControl = new NotControl(); Canvas.SetLeft(notControl, expPoint.X - 5); Canvas.SetTop(notControl, expPoint.Y - (NotGateSize / 2)); CircuitField.Children.Add(notControl); if (EndGatePoint != null) { EndGatePoint.X += notControl.Width; } return(new SimplePoint { X = expPoint.X + notControl.Width, Y = expPoint.Y }); }
public static ILocation CircularLocation(int start, int end, Strand strand, int length) { int min = Math.Min(start, end); int max = Math.Max(start, end); bool isReverse = (min != start); if (min > length) { throw new ArgumentException("Cannot process a " + "location whose lowest coordinate is less than " + "the given length " + length); } if (max <= length) { return(Location(start, end, strand, length)); } int modStart = ModulateCircularIndex(start, length); int modEnd = ModulateCircularIndex(end, length); int numberOfPasses = CompleteCircularPasses(Math.Max(start, end), length); if (isReverse) { int reversedModStart = new SimplePoint(modStart).Reverse(length).GetPosition(); int reversedModEnd = new SimplePoint(modEnd).Reverse(length).GetPosition(); modStart = reversedModStart; modEnd = reversedModEnd; start = reversedModStart; end = (length * (numberOfPasses + 1)) + modEnd; } List <ILocation> locations = new List <ILocation>(); locations.Add(new SimpleLocation(modStart, length, strand)); for (int i = 0; i < numberOfPasses; i++) { locations.Add(new SimpleLocation(1, length, strand)); } locations.Add(new SimpleLocation(1, modEnd, strand)); return(new SimpleLocation(new SimplePoint(start), new SimplePoint(end), strand, true, false, locations)); }
public SimplePoint DrawVariable(char name) { Switch sw = new Switch(name); Canvas.SetLeft(sw, 10); Canvas.SetTop(sw, VariableY); var x1 = 10 + SwitchWidth; var y1 = VariableY + SwitchHeight / 2; SimplePoint p = new SimplePoint { X = x1, Y = y1 }; VariableY += (int)sw.Height + 20; CircuitField.Children.Add(sw); return(p); }
/// <summary> /// Calculate the distance between two SimplePoints /// </summary> /// <param name="p1">first point</param> /// <param name="p2">second point</param> /// <returns>distance between two points</returns> private static double Distance(SimplePoint p1, SimplePoint p2) { double result = 0; result = Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2)); return result; }
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; }