1

Polygon 領域を色でペイントしたい。

これを行うために使用できることはわかっSymbolizerていますが、その領域を点滅させたい (タイマーで色を変更する)symbolizerため、この目的での使用は遅いようです。

私はすでにMap.OnPaintイベントを使用して、ポイントの色付きの画像を描画しています( PointLayer)。

では、グラフィックス クラスのメソッドを使用してその領域をペイントできるように、(a 内のPolygonLayer)ポリゴン フィーチャを変換するにはどうすればよいでしょうか?System.Drawing.Region

前もって感謝します。

4

1 に答える 1

1

これがデモンストレーションです。これはポリゴン固有のものですが、ポリゴンを GraphicsPath に変換する方法がわかると思います。これを使用して、グラフィック オブジェクトで選択したブラシ/ペンを使用して塗りつぶしたり描画したりできます。これは比較的単純な形状でのみテストされましたが、基本的に MapPolygonLayer と同じ描画コードを使用しているため、かなり正確であるはずです。編集モードの場合は、私が取得した方法ではなく、フィーチャから直接頂点を取得することをお勧めします。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Symbology;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// Timer for controlling flashing
        /// </summary>
        Timer timer1;

        /// <summary>
        /// True if the timer is actively flashing
        /// </summary>
        private bool timerEnabled;

        /// <summary>
        /// True if the 0 index shape should be colored yellow
        /// </summary>
        private bool highlighted;

        /// <summary>
        /// The layer with the polygon you wish to show flashing
        /// </summary>
        IMapFeatureLayer layer;

        /// <summary>
        /// Form constructor, initialize timer and paint event handler
        /// </summary>
        public Form1()
        {
            InitializeComponent();
            map1.Paint += map1_Paint;
            timer1 = new Timer();
            timer1.Interval = 1000;
            timer1.Tick += timer1_Tick;
        }

        /// <summary>
        /// Occurs when the timer ticks.  This changes the highlighting and forces the map to refresh itself.  This will not
        /// redraw all the other features, since those are cached.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void timer1_Tick(object sender, EventArgs e)
        {
            highlighted = !highlighted;
            map1.Invalidate();
        }

        /// <summary>
        /// Occurs when the map is painting.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void map1_Paint(object sender, PaintEventArgs e)
        {
            MapPolygonLayer pg = layer as MapPolygonLayer;

            // If the shape is highlighted, draw it here.
            if (pg != null && highlighted)
            {
                System.Drawing.Drawing2D.GraphicsPath borderPath = PolygonToGraphicsPath(e, pg, 0);
                e.Graphics.FillPath(Brushes.Yellow, borderPath);
                e.Graphics.DrawPath(Pens.Cyan, borderPath);
            }
        }

        /// <summary>
        /// Converts the polygon at index into a new shape.
        /// </summary>
        /// <param name="e">The paint event arguments from the paint event.</param>
        /// <param name="pg">The polygon layer</param>
        /// <param name="index">The integer zero based index of the shape to get</param>
        /// <returns></returns>
        private System.Drawing.Drawing2D.GraphicsPath PolygonToGraphicsPath(PaintEventArgs e, MapPolygonLayer pg, int index)
        {
            System.Drawing.Drawing2D.GraphicsPath borderPath = new System.Drawing.Drawing2D.GraphicsPath();

            // This controls the relationship between pixel and map coordinates
            MapArgs args = new MapArgs(map1.ClientRectangle, map1.PixelToProj(map1.ClientRectangle), e.Graphics);

            // These variables help define the offsets necessary for drawing from the args.
            double minX = args.MinX;
            double maxY = args.MaxY;
            double dx = args.Dx;
            double dy = args.Dy;

            // SoutherlandHodgman clipping is about preventing exceptions from points outside the bounds, while still keeping
            // the geometry the same inside the bounds.
            SoutherlandHodgman shClip = new SoutherlandHodgman(map1.ClientRectangle);
            ShapeRange shpx = pg.DataSet.ShapeIndices[index];

            // interleaved x/y values of all the shapes on the layer.
            double[] vertices = pg.DataSet.Vertex;
            for (int prt = 0; prt < shpx.Parts.Count; prt++)
            {
                PartRange prtx = shpx.Parts[prt];
                int start = prtx.StartIndex;
                int end = prtx.EndIndex;
                List<double[]> points = new List<double[]>();

                for (int i = start; i <= end; i++)
                {
                    double[] pt = new double[2];
                    pt[0] = (vertices[i * 2] - minX) * dx;
                    pt[1] = (maxY - vertices[i * 2 + 1]) * dy;
                    points.Add(pt);
                }
                // Actually do the SoutherlandHodgman clipping
                if (shClip != null)
                {
                    points = shClip.Clip(points);
                }
                // Prevent a lot of unnecessary drawing of duplicate pixels when zoomed out.
                List<Point> intPoints = DuplicationPreventer.Clean(points);
                if (intPoints.Count < 2)
                {
                    continue;
                }

                borderPath.StartFigure();
                Point[] pointArray = intPoints.ToArray();
                borderPath.AddLines(pointArray);
            }
            return borderPath;
        }

        /// <summary>
        /// When the first button is clicked, this will prompt the user to open a shapefile, and add it to the map.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            layer = map1.AddFeatureLayer();

        }

        /// <summary>
        /// when the second button is clicked the feature should start flashing.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (timerEnabled)
            {
                timer1.Stop();
                timerEnabled = false;
            }
            else
            {
                timer1.Start();
                timerEnabled = true;
            }

        }
    }
}
于 2014-01-17T21:55:56.690 に答える