1

Closed

Fix polygon with holes

description

Closed Jan 1, 2013 at 1:31 AM by aixchile

comments

wrote Dec 30, 2012 at 11:55 PM

Associé à l'ensemble de modifications 21162.

aixchile wrote Dec 30, 2012 at 11:56 PM

TODO : optimize code for advance poly and make it generic to handle any 2008 R2 geom type

wrote Dec 31, 2012 at 9:34 AM

Associé à l'ensemble de modifications 21166.

wrote Jan 1, 2013 at 1:31 AM

Résolu avec l'ensemble de modifications 21198.

wrote Feb 13, 2013 at 6:46 PM

wrote May 16, 2013 at 12:46 AM

kdybvik wrote Aug 1, 2013 at 7:29 PM

Can an example of this trick using the WPF control be provided? I agree that it would be fantastic if it could handle either the SQL 2008/2012 spatial stuff types, or at least be able to handle the WKT or GML that those objects provide.

aixchile wrote Aug 2, 2013 at 8:04 AM

Hi kdybvik !
The code using this trick is in BingMapsWPFViewer.ViewModel\BingMapLayersViewModel\BingMapsCustomLayers\MapVectorLayer.cs

This is an extract that should work, assuming that "this" refers to a MapLayer

This method is the main method that draws a SqlGeometry (works for SqlGeography as well, but ring extraction should be more difficult with SqlGeography)
private void DrawSqlGeometry(SqlGeometry geom)
        {
            if (geom.IsNull || geom.STIsEmpty().Value)
                return;

            // Default styles
            SolidColorBrush stroke = new SolidColorBrush(Colors.Blue);
            SolidColorBrush fill = new SolidColorBrush(Color.FromArgb(64, 0, 0, 255));

            List<FrameworkElement> shapes = new List<FrameworkElement>();

            // Draw each feature if geom is multi geom
            if (geom.InstanceOf("GeometryCollection"))
            {
                for (int i = 1; i <= geom.STNumGeometries().Value; i++)
                    shapes.AddRange(this.FromSqlGeometryToMapUIElement(geom.STGeometryN(i), stroke, fill));
            }
            else
                shapes.AddRange(this.FromSqlGeometryToMapUIElement(geom, stroke, fill));

            foreach (FrameworkElement shape in shapes)
            {
                this.Children.Add(shape);
            }
        }
This method converts SqlGeometry to Bing-compliant geometry :
private List<FrameworkElement> FromSqlGeometryToMapUIElement(SqlGeometry geom, Brush stroke, Brush fill)
        {
            List<FrameworkElement> listShape = new List<FrameworkElement>();

            try
            {
                if (!geom.STIsValid().Value)
                    geom = geom.MakeValid();

                //if (geom.STDimension().Value != 2)
                //  return listPoly;

                int numGeom = geom.STNumGeometries().Value;
                for (int i = 1; i <= numGeom; i++)
                {
                    SqlGeometry curGeom = geom.STGeometryN(i);
                    switch (curGeom.STGeometryType().ToString())
                    {
                        case "Polygon":

                            #region Polygon

                            // Must check if interior rings because of Bing Maps bug with holes
                            // See http://rbrundritt.wordpress.com/2009/02/18/advance-polygon-shapes-in-virtual-earth/
                            bool hasInteriorRings = curGeom.STNumInteriorRing().Value > 0;
                            if (hasInteriorRings)
                                listShape.AddRange(this.ExtractRings(geom, stroke));

                            MapPolygon poly = new MapPolygon();
                            poly.Stroke = hasInteriorRings ? new SolidColorBrush(Colors.Transparent) : stroke;
                            poly.Fill = fill;
                            poly.StrokeLineJoin = PenLineJoin.Bevel;

                            //poly.MouseLeftButtonUp += new MouseButtonEventHandler(poly_MouseLeftButtonUp);
                            //poly.MouseLeftButtonDown += new MouseButtonEventHandler(poly_MouseLeftButtonDown);
                            //poly.MouseLeave += (ol, el) => { txtDept.Text = "Dept: -"; };
                            //poly.MouseEnter += (o, e) => { txtDept.Text = "Dept:" + p_ShapeTag.ShapeLabel; };

                            poly.Locations = new LocationCollection();


                            int numPoints = curGeom.STNumPoints().Value;
                            for (int j = 1; j <= numPoints; j++)
                            {
                                SqlGeometry point = curGeom.STPointN(j);
                                poly.Locations.Add(new Location(point.STY.Value, point.STX.Value));
                            }

                            listShape.Add(poly);

                            #endregion Polygon

                            break;
                        case "LineString":

                            #region Polyline

                            MapPolyline polyline = new MapPolyline();
                            polyline.Stroke = stroke;
                            polyline.StrokeLineJoin = PenLineJoin.Bevel;
                            //poly.MouseLeftButtonUp += new MouseButtonEventHandler(poly_MouseLeftButtonUp);
                            //poly.MouseLeftButtonDown += new MouseButtonEventHandler(poly_MouseLeftButtonDown);
                            //poly.MouseLeave += (ol, el) => { txtDept.Text = "Dept: -"; };
                            //poly.MouseEnter += (o, e) => { txtDept.Text = "Dept:" + p_ShapeTag.ShapeLabel; };

                            polyline.Locations = new LocationCollection();

                            int numLinePoints = curGeom.STNumPoints().Value;
                            for (int j = 1; j <= numLinePoints; j++)
                            {
                                SqlGeometry point = curGeom.STPointN(j);
                                polyline.Locations.Add(new Location(point.STY.Value, point.STX.Value));
                            }

                            listShape.Add(polyline);

                            #endregion

                            break;

                        case "Point":

                            #region Point

                            Pushpin pin = new Pushpin();
                            pin.Location = new Location(curGeom.STY.Value, curGeom.STX.Value);
                            listShape.Add(pin);

                            #endregion

                            break;

                        default:
                            // Other shape types
                            DebugHelper.WriteLine(this, "Geometry type '" + curGeom.STGeometryType().ToString() + "' not implemented");
                            //throw new NotImplementedException("Geom type not implemented yet");
                            break;
                    }

                }

            }
            catch (Exception v_ex)
            {
                throw v_ex;
            }

            return listShape;
        }
And this one extract the rings in order to use the trick :
private List<FrameworkElement> ExtractRings(SqlGeometry geom, Brush stroke)
        {
            List<FrameworkElement> listRings = new List<FrameworkElement>();

            if (geom.STNumInteriorRing().Value > 0)
            {
                for (int i = 1; i <= geom.STNumInteriorRing().Value; i++)
                {
                    LocationCollection inner = new LocationCollection();
                    for (int j = 1; j <= geom.STInteriorRingN(i).STNumPoints().Value; j++)
                        inner.Add(new Location(geom.STInteriorRingN(i).STPointN(j).STY.Value, geom.STInteriorRingN(i).STPointN(j).STX.Value));

                    listRings.Add(new MapPolyline() { Locations = inner, Stroke = stroke });
                }

                LocationCollection outer = new LocationCollection();
                for (int i = 1; i <= geom.STExteriorRing().STNumPoints().Value; i++)
                    outer.Add(new Location(geom.STExteriorRing().STPointN(i).STY.Value, geom.STExteriorRing().STPointN(i).STX.Value));

                listRings.Add(new MapPolyline() { Locations = outer, Stroke = stroke });

            }

            return listRings;
        }
Let me know if you have any trouble with this.