private void createBaseGrid(object sender, EventArgs e) { Coordinate[] coord = new Coordinate[4]; double startx = 11252200; double starty = 1418500; const int width = 100; FeatureSet fs = new FeatureSet(); IFeature feature; // Add Some Columns fs.DataTable.Columns.Add(new DataColumn("ID", typeof(int))); fs.DataTable.Columns.Add(new DataColumn("Text", typeof(string))); fs.DataTable.Columns.Add(new DataColumn("Value", typeof(double))); Random rnd = new Random(); for (int i = 0; i < 110; i++) { for (int j = 0; j < 110; j++) { coord[0] = new Coordinate((i * width) + startx, (j * width) + starty); coord[1] = new Coordinate((i * width) + startx, (j * width) + starty + width); coord[2] = new Coordinate((i * width) + startx + width, (j * width) + starty + width); coord[3] = new Coordinate((i * width) + startx + width, (j * width) + starty + 0); Polygon pg = new Polygon(coord); feature = fs.AddFeature(pg); feature.DataRow.BeginEdit(); feature.DataRow["ID"] = j + i * 50; feature.DataRow["Text"] = "Hello World" + (j + i * 50).ToString(); feature.DataRow["Value"] = (rnd.NextDouble() * 360) ; feature.DataRow.EndEdit(); } } // Add a layer to the map, and we know it is a point layer so cast it specifically. IMapPolygonLayer polygonLayer = App.Map.Layers.Add(fs) as IMapPolygonLayer; // Control what the points look like through a symbolizer (or pointLayer.Symbology for categories) if (polygonLayer != null) { polygonLayer.LegendText = "grid point"; //polygonLayer.Symbolizer = new PointSymbolizer(Color.Blue, DotSpatial. ); } }
internal List <Polygon> GetPolygons(int x, int y) { int xmin = x * 1000; int ymin = y * 1000; int xmax = (x + 1) * 1000; int ymax = (y + 1) * 1000; var pp = new DSPolygon(new Coordinate[] { new Coordinate(xmin, ymin), new Coordinate(xmax, ymin), new Coordinate(xmin, ymax), new Coordinate(xmax, ymax) }); var features = shapefiles .Where(f => f.Extent.ToEnvelope().Intersects(pp.Envelope)) .SelectMany(f => f.Features); return(features .Select(f => f.BasicGeometry) .SelectMany(f => (f.GetType() == typeof(DSPolygon)) ? new DSPolygon[] { f as DSPolygon } : (f as MultiPolygon).Geometries.Select(g => g as DSPolygon) ) .Select(p => new Polygon(p)) .ToList()); }
public void Multipg() { Random rnd = new Random(); Polygon[] pg = new Polygon[50]; GeoAPI.Geometries.IPolygon[] pgcheck = new GeoAPI.Geometries.IPolygon[50]; GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory gf = new GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory(); for (int i = 0; i < 50; i++) { Coordinate center = new Coordinate((rnd.NextDouble() * 360) - 180, (rnd.NextDouble() * 180) - 90); Coordinate[] coord = new Coordinate[36]; GeoAPI.Geometries.ICoordinate[] coordscheck = new GeoAPI.Geometries.ICoordinate[36]; for (int ii = 0; ii < 36; ii++) { coord[ii] = new Coordinate(center.X + Math.Cos((ii * 10) * Math.PI / 10), center.Y + (ii * 10) * Math.PI / 10); double x = coord[ii].X; double y = coord[ii].Y; GisSharpBlog.NetTopologySuite.Geometries.Coordinate c = new GisSharpBlog.NetTopologySuite.Geometries.Coordinate(x, y); coordscheck[ii] = c; } coord[35] = new Coordinate(coord[0].X, coord[0].Y); coordscheck[35] = new GisSharpBlog.NetTopologySuite.Geometries.Coordinate(coordscheck[0].X, coordscheck[0].Y); GeoAPI.Geometries.ILinearRing ring = gf.CreateLinearRing(coordscheck); pgcheck[i] = gf.CreatePolygon(ring, null); pg[i] = new Polygon(coord); } MultiPolygon mpg = new MultiPolygon(pg); GeoAPI.Geometries.IMultiPolygon mpgcheck = gf.CreateMultiPolygon(pgcheck); for (int ii = 0; ii < mpg.Coordinates.Count; ii++) { Assert.AreEqual(mpg.Coordinates[ii].X, mpgcheck.Coordinates[ii].X); Assert.AreEqual(mpg.Coordinates[ii].Y, mpgcheck.Coordinates[ii].Y); } }
public void TwoPiecees_兩個多邊形僅Touch() { var coords1 = new List<Coordinate> { new Coordinate(1, 1), new Coordinate(2, 1), new Coordinate(2, 2), new Coordinate(1, 2), new Coordinate(1, 1) }; var p1 = new Polygon(coords1); var coords2 = new List<Coordinate> { new Coordinate(2, 1), new Coordinate(3, 1), new Coordinate(3, 2), new Coordinate(2, 2), new Coordinate(2, 1) }; var p2 = new Polygon(coords2); var merger = new MergerCustom(); var result = merger.TwoPieces(p1, p2, null, null); Assert.NotNull(result); Assert.AreEqual(2.0, result.Area, 0.00000001); }
public RuleSymbolizerPreview() { InitializeComponent(); mapPreview.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984; featureSetPoint.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984; featureSetLine.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984; featureSetPolygon.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984; DotSpatial.Topology.LineString ls = new DotSpatial.Topology.LineString(new Coordinate[] { new Coordinate(-45D, 0D), new Coordinate(45D, 0D) }); featureSetLine.AddFeature(ls); DotSpatial.Topology.Polygon polygon = new DotSpatial.Topology.Polygon(new LinearRing(new Coordinate[] { new Coordinate(90, -25), new Coordinate(135, -25), new Coordinate(135,25),new Coordinate(90, 25),new Coordinate(90, -25) })); featureSetPolygon.AddFeature(polygon); DotSpatial.Topology.Point point = new DotSpatial.Topology.Point(new Coordinate(-90D, 0D)); featureSetPoint.AddFeature(point); layerPoint = new MapPointLayer(featureSetPoint); layerLine = new MapLineLayer(featureSetLine); layerPolygon = new MapPolygonLayer(featureSetPolygon); // layerPoint.Symbolizer = new DotSpatial.Symbology.PointSymbolizer(System.Drawing.Color.DarkBlue, DotSpatial.Symbology.PointShape.Triangle, 20); mapPreview.Layers.Add(layerLine); mapPreview.Layers.Add(layerPolygon); mapPreview.Layers.Add(layerPoint); this.SizeChanged += RuleSymbolizerPreview_SizeChanged; mapPreview.ViewExtents = new Extent(-180, -180, 180, 180); mapPreview.ViewExtents.SetCenter(new Coordinate(0, 0)); }
private FeatureSet getFeatureSetFromRegularGrid(int Cols, int Rows, double MinLatitude, double MinLongitude, int ColsPerLongitude, int RowsPerLatitude) { try { FeatureSet fs = new FeatureSet(); fs.DataTable.Columns.Add("Col", typeof(int)); fs.DataTable.Columns.Add("Row", typeof(int)); for (int i = 0; i < Cols; i++) { for (int j = 0; j < Rows; j++) { Feature f = new Feature(); List <Coordinate> lstCoordinate = new List <Coordinate>(); Coordinate coordinate = new Coordinate(); coordinate.X = MinLongitude + i * (1.0000 / Convert.ToDouble(ColsPerLongitude)); coordinate.Y = MinLatitude + j * (1.0000 / Convert.ToDouble(RowsPerLatitude)); lstCoordinate.Add(coordinate); coordinate = new Coordinate(); coordinate.X = MinLongitude + (i + 1) * (1.0000 / Convert.ToDouble(ColsPerLongitude)); coordinate.Y = MinLatitude + j * (1.0000 / Convert.ToDouble(RowsPerLatitude)); lstCoordinate.Add(coordinate); coordinate = new Coordinate(); coordinate.X = MinLongitude + (i + 1) * (1.0000 / Convert.ToDouble(ColsPerLongitude)); coordinate.Y = MinLatitude + (j + 1) * (1.0000 / Convert.ToDouble(RowsPerLatitude)); lstCoordinate.Add(coordinate); coordinate = new Coordinate(); coordinate.X = MinLongitude + i * (1.0000 / Convert.ToDouble(ColsPerLongitude)); coordinate.Y = MinLatitude + (j + 1) * (1.0000 / Convert.ToDouble(RowsPerLatitude)); lstCoordinate.Add(coordinate); coordinate = new Coordinate(); coordinate.X = MinLongitude + i * (1.0000 / Convert.ToDouble(ColsPerLongitude)); coordinate.Y = MinLatitude + j * (1.0000 / Convert.ToDouble(RowsPerLatitude)); lstCoordinate.Add(coordinate); DotSpatial.Topology.Polygon p = new DotSpatial.Topology.Polygon(lstCoordinate.ToArray()); f.BasicGeometry = p; fs.AddFeature(f); fs.DataTable.Rows[i * Rows + j]["Col"] = i; fs.DataTable.Rows[i * Rows + j]["Row"] = j; } } return(fs); } catch { return(null); } }
private static MultiPolygon GetMultiPolygon(SqlGeometry sqlMultiPolygon) { var polygons = new Polygon[sqlMultiPolygon.STNumGeometries().Value]; for (var i = 1; i <= sqlMultiPolygon.STNumGeometries().Value; ++i) { polygons[i - 1] = GetPolygon(sqlMultiPolygon.STGeometryN(i)); } return(new MultiPolygon(polygons)); }
private static Geometry From(geoJson.MultiPolygon geometry) { var polygons = geometry.Coordinates; var p = new Polygon[polygons.Count]; for (var i = 0; i < polygons.Count; i++) { p[i] = From(polygons[i]); } return(new MultiPolygon(p)); }
static void DrawPolygon(DotSpatial.Topology.Polygon p, Graphics g, Pen pen, int w, int h, double minx, double miny) { if (p.Area < 5000) { return; } DrawHoles(p.Shell, g, pen, w, h, minx, miny); foreach (var hole in p.Holes) { DrawHoles(hole, g, pen, w, h, minx, miny); } }
public Polygon TwoPieces(Polygon polygon1, Polygon polygon2, LineString line1, LineString line2) { if (polygon1.Intersects(polygon2) || polygon1.Touches(polygon2)) { return polygon1.Union(polygon2) as Polygon; } else { var pg = GetConvexHull(line1, line2); return pg.Union(polygon1).Union(polygon2) as Polygon; } }
static string GetPolygonPath(Polygon polygon) { var points = new List<string>(); foreach (var coordinate in polygon.Coordinates) { var x = (0 + (coordinate.X)) / 10000; var y = (0 + (coordinate.Y * -1)) / 10000; var point = x.ToString(CultureInfo.InvariantCulture) + "," + y.ToString(CultureInfo.InvariantCulture); points.Add(point); } var @join = "M " + string.Join(" ", points) + " Z"; return @join; }
public void TwoPieces_兩個多邊形合併_沒有相交(string landno, double area) { var lands = _lands.Where(x => x.LandNo8 == landno).Select(x => new PolyLand { Code = x.Boundary, Points = x.Points }).ToList(); var merger = new Merger(_boundaries); var polygon = merger.TwoPieces(lands.First(), lands.Last()); Assert.NotNull(polygon); Assert.AreEqual(area, polygon.Area, 0.000001); var pg1 = new Polygon(lands.First().Points); Assert.True(polygon.Contains(pg1)); var pg2 = new Polygon(lands.Last().Points); Assert.True(polygon.Contains(pg2)); }
/// <summary> /// 兩塊地籍合併 /// </summary> /// <param name="polyLand1">第一塊地籍</param> /// <param name="polyLand2">第二塊地籍</param> /// <returns>合併後的多邊形</returns> public Polygon TwoPieces(PolyLand polyLand1, PolyLand polyLand2) { var polygon1 = new Polygon(polyLand1.Points); var polygon2 = new Polygon(polyLand2.Points); //if (polygon1.Intersects(polygon2) || polygon1.Touches(polygon2)) //{ // return polygon1.Union(polygon2) as Polygon; //} //else //{ SetupBorders(polyLand1); SetupBorders(polyLand2); var list = new List<Polygon>(); foreach (var border1 in polyLand1.Borders) { foreach (var border2 in polyLand2.Borders) { var pg = GetConvexHull(border1, border2); if (pg.Centroid.Distance(border1) <= _tolerance && pg.Centroid.Distance(border2) <= _tolerance ) { pg = pg.Union(polygon1).Union(polygon2) as Polygon; list.Add(pg); } } } switch (list.Count) { case 0: return null; case 1: return list.First(); default: var result = list.First(); list.Remove(result); foreach (var item in list) { result = result.Union(item) as Polygon; } return result; } //} }
private static Polygon From(geoJson.Polygon feature) { var rings = new List <LinearRing>(); foreach (var lineString in feature.Coordinates) { var coords = FromCoordinates(lineString); var lr = new LinearRing(coords); rings.Add(lr); } var inner = new ILinearRing[rings.Count - 1]; for (var i = 0; i < inner.Length; i++) { inner[i] = rings[i + 1]; } var r = new Polygon(rings[0], inner); return(r); }
public Polygon GetConvexHull(LineString line1, LineString line2) { var coords1 = new List<Coordinate> { line1.StartPoint.Coordinate, line1.EndPoint.Coordinate, line2.StartPoint.Coordinate, line2.EndPoint.Coordinate, line1.StartPoint.Coordinate }; var pg1 = new Polygon(coords1); var coords2 = new List<Coordinate> { line1.StartPoint.Coordinate, line1.EndPoint.Coordinate, line2.EndPoint.Coordinate, line2.StartPoint.Coordinate, line1.StartPoint.Coordinate }; var pg2 = new Polygon(coords2); return pg1.Area > pg2.Area ? pg1 : pg2; //return line1.Union(line2).ConvexHull() as Polygon; }
private void CreateAttributes(object sender, EventArgs e) { //http://dotspatial.codeplex.com/wikipage?title=CreateAttributes&referringTitle=Desktop_SampleCode // define the feature type for this file FeatureSet fs = new FeatureSet(FeatureType.Polygon); // Add Some Columns fs.DataTable.Columns.Add(new DataColumn("ID", typeof(int))); fs.DataTable.Columns.Add(new DataColumn("Text", typeof(string))); // create a geometry (square polygon) List<Coordinate> vertices = new List<Coordinate>(); vertices.Add(new Coordinate(11219035, 1542354)); vertices.Add(new Coordinate(11219035, 1542354 + 100)); vertices.Add(new Coordinate(11219035 + 100, 1542354 + 100)); vertices.Add(new Coordinate(11219035 + 100, 1542354 + 0)); Polygon geom = new Polygon(vertices); fs.AddFeature(geom); // add 16.01.18 // add the geometry to the featureset. IFeature feature = fs.AddFeature(geom); // now the resulting features knows what columns it has // add values for the columns feature.DataRow.BeginEdit(); feature.DataRow["ID"] = 1; feature.DataRow["Text"] = "Hello World"; feature.DataRow.EndEdit(); vertices.Clear(); vertices.Add(new Coordinate(11219035 + 100, 1542354)); vertices.Add(new Coordinate(11219035 + 100, 1542354 + 100)); vertices.Add(new Coordinate(11219035 + 200, 1542354 + 100)); vertices.Add(new Coordinate(11219035 + 200, 1542354 + 0)); geom = new Polygon(vertices); feature = fs.AddFeature(geom); // now the resulting features knows what columns it has // add values for the columns feature.DataRow.BeginEdit(); feature.DataRow["ID"] = 2; feature.DataRow["Text"] = "Hello World"; feature.DataRow.EndEdit(); // save the feature set fs.SaveAs("d:\\test.shp", true); }
private void PolygonCS(object sender, EventArgs e) { //creates a new coordinate array Coordinate[] coords = new Coordinate[10]; //creates a random point variable Random rnd = new Random(); //Creates the center coordiante for the new polygon Coordinate center = new Coordinate((rnd.NextDouble() * 360) - 180, (rnd.NextDouble() * 180) - 90); //a for loop that generates a new random X and Y value and feeds those values into the coordinate array for (int i = 0; i < 10; i++) { coords[i] = new Coordinate(center.X + Math.Cos((i * 2) * Math.PI / 18), center.Y + (i * 2) * Math.PI / 18); } //creates a new polygon from the coordinate array coords[9] = new Coordinate(coords[0].X, coords[0].Y); Polygon pg = new Polygon(coords); //new variable for the area of the polgyon Double area; area = pg.Area; //displays the area of the polygon MessageBox.Show("The Area of the polygon is: " + area); }
private void HolesCS(object sender, EventArgs e) { //Defines a new coordinate array Coordinate[] coords = new Coordinate[20]; //Defines a new random number generator Random rnd = new Random(); //defines a randomly generated center for teh polygon Coordinate center = new Coordinate((rnd.NextDouble() * 360) - 180, (rnd.NextDouble() * 180) - 90); for (int i = 0; i < 19; i++) { //generates random coordinates and adds those coordinates to the array coords[i] = new Coordinate(center.X + Math.Cos((i * 10) * Math.PI / 10), center.Y + (i * 10) * Math.PI / 10); } //sets the last coordinate equal to the first, this 'closes' the polygon coords[19] = new Coordinate(coords[0].X, coords[0].Y); //defines a new LingRing from the coordinates LinearRing Ring = new LinearRing(coords); //Repeates the process, but generates a LinearRing with a smaller area, this will be the hole in the polgyon Coordinate[] coordshole = new Coordinate[20]; for (int i = 0; i < 20; i++) { coordshole[i] = new Coordinate(center.X + Math.Cos((i * 10) * Math.PI / 20), center.Y + (i * 10) * Math.PI / 20); } coordshole[19] = new Coordinate(coordshole[0].X, coordshole[0].Y); LinearRing Hole = new LinearRing(coordshole); //This steps addes the hole LinerRing to a ILinearRing Array //A Polgyon can contain multiple holes, thus a Array of Hole is required ILinearRing[] Holes = new ILinearRing[1]; Holes[0] = Hole; //This passes the Ring, the polygon shell, and the Holes Array, the holes Polygon pg = new Polygon(Ring, Holes); //Feature f = new Feature(); FeatureSet fs = new FeatureSet(pg.FeatureType); //f = new Feature(pg); fs.Features.Add(pg); fs.SaveAs("C:\\Temp\\hole.shp", true); }
private void MpgCS(object sender, EventArgs e) { Random rnd = new Random(); Polygon[] pg = new Polygon[50]; for (int i = 0; i < 50; i++) { Coordinate center = new Coordinate((rnd.NextDouble() * 360) - 180, (rnd.NextDouble() * 180) - 90); Coordinate[] coord = new Coordinate[36]; for (int ii = 0; ii < 36; ii++) { coord[ii] = new Coordinate(center.X + Math.Cos((ii * 10) * Math.PI / 10), center.Y + (ii * 10) * Math.PI / 10); } coord[35] = new Coordinate(coord[0].X, coord[0].Y); pg[i] = new Polygon(coord); } MultiPolygon mpg = new MultiPolygon(pg); FeatureSet fs = new FeatureSet(mpg.FeatureType); fs.Features.Add(mpg); fs.SaveAs("C:\\Temp\\mpg.shp", true); }
/// <summary> /// Returns true if the element intersect the rectangle from the parent class /// </summary> /// <param name="rect">The rectangle to test must be in the virtual modeling coordinant plane</param> /// <returns></returns> public virtual bool ElementInRectangle(Rectangle rect) { IGeometry rectanglePoly; if ((rect.Height == 0) && (rect.Width == 0)) { rectanglePoly = new Topology.Point(rect.X, rect.Y); } else if (rect.Width == 0) { Topology.Point[] rectanglePoints = new Topology.Point[2]; rectanglePoints[0] = new Topology.Point(rect.X, rect.Y); rectanglePoints[1] = new Topology.Point(rect.X, rect.Y + rect.Height); rectanglePoly = new LineString(rectanglePoints); } else if (rect.Height == 0) { Topology.Point[] rectanglePoints = new Topology.Point[2]; rectanglePoints[0] = new Topology.Point(rect.X, rect.Y); rectanglePoints[1] = new Topology.Point(rect.X + rect.Width, rect.Y); rectanglePoly = new LineString(rectanglePoints); } else { Topology.Point[] rectanglePoints = new Topology.Point[5]; rectanglePoints[0] = new Topology.Point(rect.X, rect.Y); rectanglePoints[1] = new Topology.Point(rect.X, rect.Y + rect.Height); rectanglePoints[2] = new Topology.Point(rect.X + rect.Width, rect.Y + rect.Height); rectanglePoints[3] = new Topology.Point(rect.X + rect.Width, rect.Y); rectanglePoints[4] = new Topology.Point(rect.X, rect.Y); rectanglePoly = new Polygon(new LinearRing(rectanglePoints)); } switch (Shape) { case ModelShape.Rectangle: return (rect.IntersectsWith(Rectangle)); case ModelShape.Ellipse: int b = Height / 2; int a = Width / 2; Topology.Point[] ellipsePoints = new Topology.Point[(4 * a) + 1]; for (int x = -a; x <= a; x++) { if (x == 0) { ellipsePoints[x + a] = new Topology.Point(Location.X + x + a, Location.Y); ellipsePoints[3 * a - x] = new Topology.Point(Location.X + x + a, Location.Y + Height); } else { ellipsePoints[x + a] = new Topology.Point(Location.X + x + a, Location.Y + b - Math.Sqrt(Math.Abs(((b * b * x * x) / (a * a)) - (b * b)))); ellipsePoints[3 * a - x] = new Topology.Point(Location.X + x + a, Location.Y + b + Math.Sqrt(Math.Abs(((b * b * x * x) / (a * a)) - (b * b)))); } } Polygon ellipsePoly = new Polygon(new LinearRing(ellipsePoints)); return (ellipsePoly.Intersects(rectanglePoly)); case ModelShape.Triangle: Topology.Point[] trianglePoints = new Topology.Point[4]; trianglePoints[0] = new Topology.Point(Location.X, Location.Y); trianglePoints[1] = new Topology.Point(Location.X, Location.Y + Height); trianglePoints[2] = new Topology.Point(Location.X + Width - 5, Location.Y + ((Height - 5) / 2)); trianglePoints[3] = new Topology.Point(Location.X, Location.Y); Polygon trianglePoly = new Polygon(new LinearRing(trianglePoints)); return (trianglePoly.Intersects(rectanglePoly)); default: return false; } }
/// <summary> /// If the FeatureType is polygon, this is the code for converting the vertex array /// into a feature. /// </summary> /// <param name="index"> /// </param> /// <returns> /// </returns> protected IFeature GetPolygon(int index) { if (FeatureGeometryFactory == null) { FeatureGeometryFactory = GeometryFactory.Default; } Feature feature = new Feature { Envelope = ShapeIndices[index].Extent.ToEnvelope() }; ShapeRange shape = ShapeIndices[index]; List<ILinearRing> shells = new List<ILinearRing>(); List<ILinearRing> holes = new List<ILinearRing>(); foreach (PartRange part in shape.Parts) { List<Coordinate> coords = new List<Coordinate>(); int i = part.StartIndex; foreach (Vertex d in part) { Coordinate c = new Coordinate(d.X, d.Y); if (M != null && M.Length > 0) { c.M = M[i]; } if (Z != null && Z.Length > 0) { c.Z = Z[i]; } i++; coords.Add(c); } ILinearRing ring = FeatureGeometryFactory.CreateLinearRing(coords); if (shape.Parts.Count == 1) { shells.Add(ring); } else { if (CgAlgorithms.IsCounterClockwise(ring.Coordinates)) { holes.Add(ring); } else { shells.Add(ring); } } } // Now we have a list of all shells and all holes List<ILinearRing>[] holesForShells = new List<ILinearRing>[shells.Count]; for (int i = 0; i < shells.Count; i++) { holesForShells[i] = new List<ILinearRing>(); } // Find holes foreach (ILinearRing t in holes) { ILinearRing testRing = t; ILinearRing minShell = null; IEnvelope minEnv = null; IEnvelope testEnv = testRing.EnvelopeInternal; Coordinate testPt = testRing.Coordinates[0]; ILinearRing tryRing; for (int j = 0; j < shells.Count; j++) { tryRing = shells[j]; IEnvelope tryEnv = tryRing.EnvelopeInternal; if (minShell != null) { minEnv = minShell.EnvelopeInternal; } bool isContained = false; if (tryEnv.Contains(testEnv) && (CgAlgorithms.IsPointInRing(testPt, tryRing.Coordinates) || PointInList(testPt, tryRing.Coordinates))) { isContained = true; } // Check if this new containing ring is smaller than the current minimum ring if (isContained) { if (minShell == null || minEnv.Contains(tryEnv)) { minShell = tryRing; } holesForShells[j].Add(t); } } } IPolygon[] polygons = new Polygon[shells.Count]; for (int i = 0; i < shells.Count; i++) { polygons[i] = FeatureGeometryFactory.CreatePolygon(shells[i], holesForShells[i].ToArray()); } if (polygons.Length == 1) { feature.BasicGeometry = polygons[0]; } else { // It's a multi part feature.BasicGeometry = FeatureGeometryFactory.CreateMultiPolygon(polygons); } // feature.FID = feature.RecordNumber; FID is now dynamic feature.ParentFeatureSet = this; feature.ShapeIndex = shape; feature.RecordNumber = shape.RecordNumber; feature.ContentLength = shape.ContentLength; feature.ShapeType = shape.ShapeType; // Attributes handled in the overridden case return feature; }
/// <summary> /// Executes the ClipPolygonWithLine Operation tool programaticaly. /// Ping deleted static for external testing 01/2010 /// </summary> /// <param name="input1">The input Polygon FeatureSet.</param> /// <param name="input2">The input Polyline FeatureSet.</param> /// <param name="output">The output Polygon FeatureSet.</param> /// <param name="cancelProgressHandler">The progress handler.</param> /// <returns></returns> public bool Execute( IFeatureSet input1, IFeatureSet input2, IFeatureSet output, ICancelProgressHandler cancelProgressHandler) { // Validates the input and output data if (input1 == null || input2 == null || output == null) { return false; } if (cancelProgressHandler.Cancel) { return false; } IFeature polygon = input1.Features[0]; IFeature line = input2.Features[0]; IFeatureSet resultFs = new FeatureSet(FeatureType.Polygon); int previous = 0; if (DoClipPolygonWithLine(ref polygon, ref line, ref output) == false) { throw new SystemException(TextStrings.Exceptioninclipin); } int intFeature = output.Features.Count; for (int i = 0; i < intFeature; i++) { Polygon poly = new Polygon(output.Features[i].Coordinates); resultFs.AddFeature(poly); int current = Convert.ToInt32(Math.Round(i * 100D / intFeature)); // only update when increment in percentage if (current > previous) { cancelProgressHandler.Progress(string.Empty, current, current + TextStrings.progresscompleted); } previous = current; } cancelProgressHandler.Progress(string.Empty, 100, 100 + TextStrings.progresscompleted); resultFs.SaveAs(output.Filename, true); return true; }
void p() { FeatureSet fs = new FeatureSet(FeatureType.Polygon); fs.DataTable.Columns.Add(new DataColumn("ID", typeof(int))); fs.DataTable.Columns.Add(new DataColumn("Text", typeof(string))); List<Coordinate> vertices = new List<Coordinate>(); // vertices.Add(new Coordinate(0, 0)); // vertices.Add(new Coordinate(0, 100)); // vertices.Add(new Coordinate(100, 100)); // vertices.Add(new Coordinate(100, 0)); vertices.Add(new Coordinate(242846.81386332, 7528087.29373347)); vertices.Add(new Coordinate(242854.625931002, 7528087.29373347)); vertices.Add(new Coordinate(242854.625931002, 7528094.1633412)); vertices.Add(new Coordinate(242846.81386332, 7528094.1633412)); Polygon geom = new Polygon(vertices); IFeature feature = fs.AddFeature(geom); appManager1.Map.Layers.Add(fs); }
private void MultypgFSCS(object sender, EventArgs e) { Random rnd = new Random(); Polygon[] pg = new Polygon[100]; Feature f = new Feature(); FeatureSet fs = new FeatureSet(f.FeatureType); for (int i = 0; i < 100; i++) { Coordinate center = new Coordinate((rnd.Next(50) * 360) - 180, (rnd.Next(60) * 180) - 90); Coordinate[] coord = new Coordinate[50]; for (int ii = 0; ii < 50; ii++) { coord[ii] = new Coordinate(center.X + Math.Cos((ii * 10) * Math.PI / 10), center.Y + (ii * 10) * Math.PI / 10); } coord[49] = new Coordinate(coord[0].X, coord[0].Y); pg[i] = new Polygon(coord); fs.Features.Add(pg[i]); } fs.SaveAs("C:\\Temp\\test.shp", true); }
public void shpWrite(string path) { fs.DataTable.Columns.Add(new DataColumn("ID", typeof(int))); DataColumn col = new DataColumn("Project", typeof(string)); col.MaxLength = 50; fs.DataTable.Columns.Add(col); fs.DataTable.Columns.Add(new DataColumn("Area", typeof(double))); IFeatureSet fsource = FeatureSet.Open(@"Sample\Sample.shp"); fs.Projection = fsource.Projection; fsource.Close(); int ID = 0; foreach (Geometries geometry in project.Geometries) { ID++; Polygon[] pgs = new Polygon[geometry.Polygons.Count]; int i = 0; //foreach (Geometries geometry in project.Geometries) { foreach (GeoPolygon polygon in geometry.Polygons) { List<Coordinate> vertices = new List<Coordinate>(); //polygon.Points.Reverse(); if (polygon.Circle>1&&!polygon.GetDirection()) { polygon.Points.Reverse(); } else if (polygon.Circle==1&&polygon.GetDirection()) { polygon.Points.Reverse(); } foreach (GeoPoint point in polygon.Points) { Coordinate vertice = new Coordinate(); vertice.X = point.X; vertice.Y = point.Y; vertices.Add(vertice); } Polygon geom = new Polygon(vertices); pgs[i] = geom; i++; } //} MultiPolygon geoms = new MultiPolygon(pgs); geoms.ToText(); IFeature feature = fs.AddFeature(geoms); feature.DataRow.BeginEdit(); feature.DataRow["ID"] = ID; feature.DataRow["Project"] = project.Name; //feature.DataRow["Area"] = feature.Area(); feature.DataRow.EndEdit(); } //fs.Projection = ProjectionInfo.(@"F:\数据\2013SHP\DLTB.shp"); //fs.ProjectionString = " +x_0=40500000 +y_0=0 +lat_0=0 +lon_0=120 +proj=tmerc +a=6378140 +b=6356755.28815753 +no_defs"; fs.SaveAs(path, true); fs.Dispose(); GeoRead gr = new GeoRead(path); gr.shpAreaReCalculate(); //fs = FeatureSet.Open(path); }
/// <summary> /// 1.將多邊形內部的小碎地(小於1平方公尺)移除 /// </summary> /// <param name="polygon"></param> public Polygon CleanupPolygon(Polygon polygon) { if (polygon.Holes.Any(x => x.Envelope.Area() < 1)) { polygon = new Polygon(polygon.ExteriorRing.Coordinates); var holes = polygon.Holes.Where(x => x.Envelope.Area() > 1); foreach (var hole in holes) { polygon.Union(new Polygon(hole.Coordinates)); } } return polygon; }
/// <summary> /// updates the auto-filling X and Y coordinates /// </summary> /// <param name="e"></param> protected override void OnMouseMove(GeoMouseArgs e) { if (_standBy) { return; } if (_coordinates == null || _coordinates.Count == 0) { return; } Coordinate c1 = e.GeographicLocation; if (_measureDialog.MeasureMode == MeasureMode.Distance) { double dist = GetDist(c1); _measureDialog.TotalDistance = _previousDistance + _currentDistance + dist; } else { List<Coordinate> tempPolygon = _coordinates.ToList(); tempPolygon.Add(c1); if (tempPolygon.Count < 3) { if (tempPolygon.Count == 2) { Rectangle r = Map.ProjToPixel(new LineString(tempPolygon).Envelope.ToExtent()); r.Inflate(20, 20); Map.Invalidate(r); } _mousePosition = e.Location; return; } Polygon pg = new Polygon(new LinearRing(tempPolygon)); double area = GetArea(tempPolygon); _measureDialog.TotalArea = area; Rectangle rr = Map.ProjToPixel(pg.Envelope.ToExtent()); rr.Inflate(20, 20); Map.Invalidate(rr); _mousePosition = e.Location; } if (_coordinates.Count > 0) { List<Point> points = _coordinates.Select(coord => Map.ProjToPixel(coord)).ToList(); Rectangle oldRect = SymbologyGlobal.GetRectangle(_mousePosition, points[points.Count - 1]); Rectangle newRect = SymbologyGlobal.GetRectangle(e.Location, points[points.Count - 1]); Rectangle invalid = Rectangle.Union(newRect, oldRect); invalid.Inflate(20, 20); Map.Invalidate(invalid); } _mousePosition = e.Location; base.OnMouseMove(e); }
private static IEnumerable <OmrådeMedGeometry> GreateGrid(int zoom) { List <OmrådeMedGeometry> p = new List <OmrådeMedGeometry>(); var bb = WebMercator.BoundingBox; int max = 2 << (zoom + 3); var rnd = new Random(); for (int i = 0; i < 2; i++) { var Width = bb.Maximum.X - bb.Minimum.X; var Height = bb.Maximum.Y - bb.Minimum.Y; double x1 = rnd.NextDouble() * Width + bb.Minimum.X; double y1 = rnd.NextDouble() * Height + bb.Minimum.Y; double x2 = rnd.NextDouble() * Width + bb.Minimum.X; double y2 = rnd.NextDouble() * Height + bb.Minimum.Y; double x3 = rnd.NextDouble() * Width + bb.Minimum.X; double y3 = rnd.NextDouble() * Height + bb.Minimum.Y; var polygon = new List <Coordinate>(); polygon.AddRange(new[] { new Coordinate(x1, y1), new Coordinate(x2, y2), new Coordinate(x3, y3), new Coordinate(x1, y1) }); var poly = new Polygon(polygon); var o = new Område(-1, AreaType.Grid) { Number = 1 }; p.Add(new OmrådeMedGeometry(o, poly)); } double left = (bb.Maximum.X - bb.Minimum.X) / 40 + bb.Minimum.X; double right = bb.Maximum.X - (bb.Maximum.X - bb.Minimum.X) / 40; double top = bb.Maximum.Y - (bb.Maximum.Y - bb.Minimum.Y) / 40; double bottom = bb.Minimum.Y + (bb.Maximum.Y - bb.Minimum.Y) / 40; var dy = (top - bottom) * max / 500.0; //for (double x = bb.Left; x <= bb.Right; x += dx) // p.Add(new Polygon(new[] { new Point(x, bb.Bottom), new Point(bb.Right - x, bb.Top), new Point(0, 0), new Point(x, bb.Bottom) })); for (double y = bottom; y <= top; y += dy) { var polygon = new List <Coordinate>(); polygon.AddRange(new[] { new Coordinate(left + 1, y), new Coordinate(right - 1, y), new Coordinate(right - 1, y + dy / 2 - 1), new Coordinate(left + 1, y + dy / 2 - 1), new Coordinate(left + 1, y) }); var o1 = new Område(-1, AreaType.Grid) { Number = 1 }; p.Add(new OmrådeMedGeometry(o1, new LineString(polygon))); } var p2 = new List <Coordinate>(); p2.AddRange(new[] { new Coordinate(bb.Minimum.X, bb.Minimum.Y), new Coordinate(bb.Maximum.X, bb.Minimum.Y), new Coordinate(bb.Maximum.X, bb.Maximum.Y), new Coordinate(bb.Minimum.X, bb.Maximum.Y), new Coordinate(bb.Minimum.X, bb.Minimum.Y) }); var område = new Område(-1, AreaType.Grid) { Number = 1 }; p.Add(new OmrådeMedGeometry(område, new LineString(p2))); return(p); }
/// <summary> /// Returns true if the element intersect the rectangle from the parent class /// </summary> /// <param name="rect">The rectangle to test must be in the virtual modeling coordinant plane</param> /// <returns></returns> public override bool ElementInRectangle(Rectangle rect) { IGeometry rectanglePoly; if ((rect.Height == 0) && (rect.Width == 0)) { rectanglePoly = new Topology.Point(rect.X, rect.Y); } else if (rect.Width == 0) { Topology.Point[] rectanglePoints = new Topology.Point[2]; rectanglePoints[0] = new Topology.Point(rect.X, rect.Y); rectanglePoints[1] = new Topology.Point(rect.X, rect.Y + rect.Height); rectanglePoly = new LineString(rectanglePoints); } else if (rect.Height == 0) { Topology.Point[] rectanglePoints = new Topology.Point[2]; rectanglePoints[0] = new Topology.Point(rect.X, rect.Y); rectanglePoints[1] = new Topology.Point(rect.X + rect.Width, rect.Y); rectanglePoly = new LineString(rectanglePoints); } else { Topology.Point[] rectanglePoints = new Topology.Point[5]; rectanglePoints[0] = new Topology.Point(rect.X, rect.Y); rectanglePoints[1] = new Topology.Point(rect.X, rect.Y + rect.Height); rectanglePoints[2] = new Topology.Point(rect.X + rect.Width, rect.Y + rect.Height); rectanglePoints[3] = new Topology.Point(rect.X + rect.Width, rect.Y); rectanglePoints[4] = new Topology.Point(rect.X, rect.Y); rectanglePoly = new Polygon(new LinearRing(rectanglePoints)); } if (Shape == ModelShape.Arrow) { Topology.Point[] arrowPoints = new Topology.Point[_arrowPath.PointCount]; for (int i = 0; i < _arrowPath.PointCount; i++) { arrowPoints[i] = new Topology.Point(_arrowPath.PathPoints[i].X + Location.X, _arrowPath.PathPoints[i].Y + Location.Y); } LineString arrowLine = new LineString(arrowPoints); return (arrowLine.Intersects(rectanglePoly)); } return false; }
/// <summary> /// If the input geometry is a singular basic geometry, this will become a collection of 1 geometry. /// If the input geometry is a multi- basic geometry, this will simply ensure that each member /// is upgraded to a full geometry. /// </summary> /// <param name="inGeometry"></param> /// <param name="inFactory"></param> public GeometryCollection(IBasicGeometry inGeometry, IGeometryFactory inFactory) : base(inFactory) { if (inGeometry == null) { _geometries = new IGeometry[] { }; return; } IBasicPolygon pg = inGeometry.GetBasicGeometryN(0) as IBasicPolygon; if (pg != null) { _geometries = new IGeometry[inGeometry.NumGeometries]; for (int iGeom = 0; iGeom < inGeometry.NumGeometries; iGeom++) { pg = inGeometry.GetBasicGeometryN(iGeom) as IBasicPolygon; _geometries[iGeom] = new Polygon(pg); } return; } IBasicPoint pt = inGeometry.GetBasicGeometryN(0) as IBasicPoint; if (pt != null) { _geometries = new IGeometry[inGeometry.NumGeometries]; for (int iGeom = 0; iGeom < inGeometry.NumGeometries; iGeom++) { pt = inGeometry.GetBasicGeometryN(iGeom) as IBasicPoint; _geometries[iGeom] = new Point(pt); } return; } IBasicLineString ls = inGeometry.GetBasicGeometryN(0) as IBasicLineString; if (ls != null) { _geometries = new IGeometry[inGeometry.NumGeometries]; for (int iGeom = 0; iGeom < inGeometry.NumGeometries; iGeom++) { ls = inGeometry.GetBasicGeometryN(iGeom) as IBasicLineString; _geometries[iGeom] = new LineString(ls); } return; } }
void p2() { var sel = appManager1.Map.GetPointLayers()[0].Selection.ToFeatureList(); FeatureSet fs = new FeatureSet(FeatureType.Polygon); List<Coordinate> vertices = new List<Coordinate>(); vertices.Add(new Coordinate(sel[0].Coordinates[0])); vertices.Add(new Coordinate(sel[1].Coordinates[0])); vertices.Add(new Coordinate(sel[3].Coordinates[0])); vertices.Add(new Coordinate(sel[2].Coordinates[0])); Polygon geom = new Polygon(vertices); IFeature feature = fs.AddFeature(geom); appManager1.Map.Layers.Add(fs); MessageBox.Show(geom.Area.ToString()); }
/// <summary> /// Creates a Polygon or MultiPolygon from this Polygon shape. /// </summary> /// <param name="factory">The IGeometryFactory to use to create the new IGeometry.</param> /// <returns>The IPolygon or IMultiPolygon created from this shape.</returns> protected IGeometry FromPolygon(IGeometryFactory factory) { if (factory == null) factory = Geometry.DefaultFactory; List<ILinearRing> shells = new List<ILinearRing>(); List<ILinearRing> holes = new List<ILinearRing>(); foreach (PartRange part in _shapeRange.Parts) { List<Coordinate> coords = new List<Coordinate>(); int i = part.StartIndex; foreach (Vertex d in part) { Coordinate c = new Coordinate(d.X, d.Y); if (M != null && M.Length > 0) c.M = M[i]; if (Z != null && Z.Length > 0) c.Z = Z[i]; i++; coords.Add(c); } ILinearRing ring = factory.CreateLinearRing(coords); if (_shapeRange.Parts.Count == 1) { shells.Add(ring); } else { if (CgAlgorithms.IsCounterClockwise(ring.Coordinates)) { holes.Add(ring); } else { shells.Add(ring); } } } //// Now we have a list of all shells and all holes List<ILinearRing>[] holesForShells = new List<ILinearRing>[shells.Count]; for (int i = 0; i < shells.Count; i++) { holesForShells[i] = new List<ILinearRing>(); } // Find holes foreach (ILinearRing t in holes) { ILinearRing testRing = t; ILinearRing minShell = null; IEnvelope minEnv = null; IEnvelope testEnv = testRing.EnvelopeInternal; Coordinate testPt = testRing.Coordinates[0]; ILinearRing tryRing; for (int j = 0; j < shells.Count; j++) { tryRing = shells[j]; IEnvelope tryEnv = tryRing.EnvelopeInternal; if (minShell != null) minEnv = minShell.EnvelopeInternal; bool isContained = false; if (tryEnv.Contains(testEnv) && (CgAlgorithms.IsPointInRing(testPt, tryRing.Coordinates) || (PointInList(testPt, tryRing.Coordinates)))) { isContained = true; } // Check if this new containing ring is smaller than the current minimum ring if (isContained) { if (minShell == null || minEnv.Contains(tryEnv)) { minShell = tryRing; } holesForShells[j].Add(t); } } } IPolygon[] polygons = new Polygon[shells.Count]; for (int i = 0; i < shells.Count; i++) { polygons[i] = factory.CreatePolygon(shells[i], holesForShells[i].ToArray()); } if (polygons.Length == 1) { return polygons[0]; } // It's a multi part return factory.CreateMultiPolygon(polygons); }
/// <summary> /// Takes an array of simple polygons and combines them into one multi-part shape. /// </summary> /// <param name="parts">The array of polygons.</param> /// <param name="resultShp">The resulting multi-part shape.</param> public static void CombineParts(ref IFeature[] parts, ref IFeature resultShp) { int numParts = parts.Length; Polygon po = new Polygon(parts[0].Coordinates); Polygon poly; for (int i = 0; i <= numParts - 1; i++) { poly = new Polygon(parts[i].Coordinates); po = poly.Union(po) as Polygon; } resultShp = new Feature(po); }
private IGeometry CreatePolygonData(bool type) { double size = this.spatial.NumberOfLags * 2 * this.spatial.LagSize; Coordinate center; if (type) center = new Coordinate(500000 + (size / 2), size / 2); else center = new Coordinate(0,0); Coordinate[] array = new Coordinate[6]; array[0] = center; array[1] = this.spatial.AzimuthDist(center, azimuth + tolerance, bandWidth*this.spatial.LagSize); array[2] = this.spatial.AzimuthDist(array[1], azimuth, this.spatial.LagValue.numLags * this.spatial.LagSize); array[3] = this.spatial.AzimuthDist(array[2], azimuth + Math.PI + Math.PI/2, Math.Sin(tolerance) * (bandWidth * this.spatial.LagSize) * 2); array[4] = this.spatial.AzimuthDist(array[3], azimuth + Math.PI, this.spatial.LagValue.numLags * this.spatial.LagSize); array[5] = center; LinearRing shell = new LinearRing(array); Polygon poly = new Polygon(shell); return poly; }
private IBasicGeometry GetPolygon(MultiSurfaceType multi) { Polygon[] p = new Polygon[multi.SurfaceMemberItems.Count]; ; int npoly = 0; foreach (SurfacePropertyType member in multi.SurfaceMemberItems) { ILinearRing shell = null; ILinearRing[] holes = null; PolygonType sur = ExtractShellPolygon(ref shell, member); if (sur.Interior.Count == 0 && shell !=null) p[npoly] = new Polygon(shell); else { holes = new ILinearRing[sur.Interior.Count]; ExtractInteriorPolygon(holes, sur); p[npoly] = new Polygon(shell, holes); } npoly++; } return new MultiPolygon(p); }
/// <summary> /// The Voronoi Graph calculation creates the lines that form a voronoi diagram. /// </summary> /// <param name="points">The points to use for creating the tesselation.</param> /// <param name="result">The output featureset.</param> /// <param name="cropToExtent">The normal polygons have sharp angles that extend like stars. /// Cropping will ensure that the original featureset extent plus a small extra buffer amount /// is the outer extent of the polygons. Errors seem to occur if the exact extent is used.</param> public static void VoronoiPolygons(IFeatureSet points, IFeatureSet result, bool cropToExtent) { double[] vertices = points.Vertex; VoronoiGraph gp = Fortune.ComputeVoronoiGraph(vertices); Extent ext = points.Extent; ext.ExpandBy(ext.Width / 100, ext.Height / 100); IEnvelope env = ext.ToEnvelope(); IPolygon bounds = env.ToPolygon(); // Convert undefined coordinates to a defined coordinate. HandleBoundaries(gp, env); for (int i = 0; i < vertices.Length / 2; i++) { List<VoronoiEdge> myEdges = new List<VoronoiEdge>(); Vector2 v = new Vector2(vertices, i * 2); foreach (VoronoiEdge edge in gp.Edges) { if (!v.Equals(edge.RightData) && !v.Equals(edge.LeftData)) { continue; } myEdges.Add(edge); } List<Coordinate> coords = new List<Coordinate>(); VoronoiEdge firstEdge = myEdges[0]; coords.Add(firstEdge.VVertexA.ToCoordinate()); coords.Add(firstEdge.VVertexB.ToCoordinate()); Vector2 previous = firstEdge.VVertexB; myEdges.Remove(myEdges[0]); Vector2 start = firstEdge.VVertexA; while (myEdges.Count > 0) { for (int j = 0; j < myEdges.Count; j++) { VoronoiEdge edge = myEdges[j]; if (edge.VVertexA.Equals(previous)) { previous = edge.VVertexB; Coordinate c = previous.ToCoordinate(); coords.Add(c); myEdges.Remove(edge); break; } // couldn't match by adding to the end, so try adding to the beginning if (edge.VVertexB.Equals(start)) { start = edge.VVertexA; coords.Insert(0, start.ToCoordinate()); myEdges.Remove(edge); break; } // I don't like the reverse situation, but it seems necessary. if (edge.VVertexB.Equals(previous)) { previous = edge.VVertexA; Coordinate c = previous.ToCoordinate(); coords.Add(c); myEdges.Remove(edge); break; } if (edge.VVertexA.Equals(start)) { start = edge.VVertexB; coords.Insert(0, start.ToCoordinate()); myEdges.Remove(edge); break; } } } for (int j = 0; j < coords.Count; j++) { Coordinate cA = coords[j]; // Remove NAN values if (double.IsNaN(cA.X) || double.IsNaN(cA.Y)) { coords.Remove(cA); } // Remove duplicate coordinates for (int k = j + 1; k < coords.Count; k++) { Coordinate cB = coords[k]; if (cA.Equals2D(cB)) { coords.Remove(cB); } } } foreach (Coordinate coord in coords) { if (double.IsNaN(coord.X) || double.IsNaN(coord.Y)) { coords.Remove(coord); } } if (coords.Count <= 2) { continue; } Polygon pg = new Polygon(coords); if (cropToExtent) { try { IGeometry g = pg.Intersection(bounds); IPolygon p = g as IPolygon; if (p != null) { Feature f = new Feature(p, result); f.CopyAttributes(points.Features[i]); } } catch (Exception) { Feature f = new Feature(pg, result); f.CopyAttributes(points.Features[i]); } } else { Feature f = new Feature(pg, result); f.CopyAttributes(points.Features[i]); } } return; }
public static bool PointInPolygon(Polygon polygon, Models.Location Location) { double[] pointXy = { Location.Latitude, Location.Longitude }; var pointZ = new double[] { 0 }; TransformCoords(ref pointXy, ref pointZ, 1); var middle = GeometryFactory.Default.CreatePoint(new Coordinate(pointXy[0], pointXy[1])); return middle.Within(polygon); }