Beispiel #1
0
        public Layer readImpl(string filename)
        {
            // split filename in path and filename
            string[] split = filename.Split('\\');
            string name = split.Last();
            // remove extension
            name = name.Substring(0, name.Length - 4);
            string path = filename.Substring(0, filename.Length - name.Length - 4);

            layer = new Layer(name);

            // read .prj-file with same name or with name 'default.prj'
            string prjName = filename.Substring(0, filename.Length - 3) + "prj";
            if (File.Exists(prjName))
                layer.Projection = PrjReader.read(prjName);
            else if (File.Exists(path + "default.prj"))
                layer.Projection = PrjReader.read(path + "default.prj");
            else
            {
                // warning message if missing prj file
                string msg = "No projection da found. Assuming " + SGIS.App.getSrsName();
                MessageBox.Show(msg, "Missing spatial reference system: " + name, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            // try reading attribute file with same name
            string dbfName = filename.Substring(0, filename.Length - 3) + "dbf";
            if (File.Exists(dbfName))
                layer.DataTable = DbfReader.read(dbfName);

            // create stream from file
            FileStream f = File.Open(filename, FileMode.Open);
            br = new BinaryReaderExtension(f);
            pos = 0;
            length = (int)br.BaseStream.Length;

            readHeader();

            // set bounding box from values in header
            layer.Boundingbox = new Envelope(minx, maxx, miny, maxy);
            layer.createQuadTree();

            // content starts at pos 100
            pos = 100;

            // read all shapes until end
            while (pos < length)
                readShape();

            br.Close();

            // features now converted to application srs
            layer.Projection = SGIS.App.SRS;
            return layer;
        }
Beispiel #2
0
        // copy selected feature to new layer
        private void toLayerButton_Click(object sender, EventArgs e)
        {
            toolBuilder.addHeader("Export selection");
            // textbox for new layer name
            TextBox textbox = toolBuilder.addTextboxWithCaption("Layer name:");
            Label errorLabel = toolBuilder.addErrorLabel();
            // button for performing copy
            Button selectButton = toolBuilder.addButton("Copy selection", (Layer l) =>
            {
                if (textbox.Text.Length == 0)
                {
                    errorLabel.Text = "Provide a name";
                    return;
                }

                Layer newl = new Layer(textbox.Text);
                // copy attributes
                newl.DataTable = l.DataTable;
                // copy features
                foreach (Feature f in l.Selected)
                    newl.addFeature(new Feature((Geometry)f.Geometry.Clone(), f.ID));
                newl.calculateBoundingBox();
                newl.createQuadTree();
                Layers.Insert(0, newl);
                // select newly made layer
                layerList.SelectedItem = newl;
            });

            // change default new layer name when new layer is selected
            toolBuilder.resetAction = (Layer l) =>
            {
                textbox.Text = (l == null) ? "" : l.Name + "_copy";
            };
            toolBuilder.reset();
        }
Beispiel #3
0
        // perform union on currently selected layer
        private void unionButton_Click(object sender, EventArgs e)
        {
            toolBuilder.addHeader("Union");
            // textbox for new layername
            TextBox textbox = toolBuilder.addTextboxWithCaption("New layername:");
            Label errorLabel = toolBuilder.addErrorLabel();
            Button button = toolBuilder.addButton("Union", (Layer l) =>
            {
                // user has not set new layername
                if (textbox.Text.Length == 0)
                {
                    toolBuilder.setError("Provide name");
                    return;
                }
                // create temporary layer
                Layer copyLayer = new Layer(l.Name);
                copyLayer.Boundingbox = new Envelope(l.Boundingbox);
                copyLayer.createQuadTree();

                // copy all features to temp layer
                foreach (Feature f in l.Features.Values)
                    copyLayer.addFeature(new Feature((IGeometry)f.Geometry.Clone(), f.ID));

                // create new layer with same boundingbox
                Layer newLayer = new Layer(textbox.Text);
                newLayer.Boundingbox = new Envelope(l.Boundingbox);
                newLayer.createQuadTree();

                // init progress bar
                int numFeatures = copyLayer.Features.Values.Count;
                progressLabel.Text = "Performing union";
                progressBar.Minimum = 0;
                progressBar.Maximum = numFeatures;

                BackgroundWorker bw = new BackgroundWorker();
                bw.WorkerReportsProgress = true;
                // perform merge in another thread
                bw.DoWork += (object wsender, DoWorkEventArgs we) =>
                {
                    // threadsafe list of merged features
                    ConcurrentBag<Feature> newFeatures = new ConcurrentBag<Feature>();
                    var finished = new CountdownEvent(1);
                    Object _lock = new object();
                    // create thread function
                    var merge = new WaitCallback((state) =>
                    {
                        Random rnd = new Random();
                        while (true)
                        {
                            Feature f;
                            lock (_lock)
                            {
                                // break if no more features
                                if (copyLayer.Features.Count == 0)
                                    break;
                                // get random index
                                int index = rnd.Next(copyLayer.Features.Count);
                                // get corresponding random feature
                                f = copyLayer.Features[copyLayer.Features.Keys.ToList()[index]];
                                // remove feature from layer
                                copyLayer.delFeature(f);
                            }
                            f.ID = -1;
                            while (true)
                            {
                                List<Feature> intersects;
                                // aquire lock to avoid race conditions
                                lock (_lock)
                                {
                                    // get all features intersecting feature
                                    intersects = copyLayer.getWithin(f.Geometry);
                                    // remove features from layer
                                    foreach (Feature intersect in intersects)
                                        copyLayer.delFeature(intersect);
                                }
                                // if no intersects, no merging is necessary
                                if (intersects.Count == 0)
                                    break;
                                // merge all features
                                foreach (Feature intersect in intersects)
                                {
                                    f = new Feature(f.Geometry.Union(intersect.Geometry));
                                    bw.ReportProgress(1);
                                }
                            }
                            // add feature to list of new features
                            newFeatures.Add(f);
                        }
                        finished.Signal();
                    });
                    // spawn eight threads, this is not always optimal but a good approximation
                    for (int i = 0; i < 8; i++)
                    {
                        finished.AddCount();
                        ThreadPool.QueueUserWorkItem(merge);
                    }
                    finished.Signal();
                    finished.Wait();

                    bw.ReportProgress(-newFeatures.Count);
                    // add all merged features back to temp layer
                    foreach (Feature f in newFeatures)
                        copyLayer.addFeature(f);
                    newFeatures = new ConcurrentBag<Feature>();
                    finished = new CountdownEvent(1);
                    // perform a final single threaded merge
                    merge(false);

                    // add all final merged features to new layer
                    foreach (Feature f in newFeatures)
                        newLayer.addFeature(f);
                };
                bw.RunWorkerCompleted += (object wsender, RunWorkerCompletedEventArgs we) =>
                {
                    // reset progress bar
                    progressBar.Value = 0;
                    progressLabel.Text = "";

                    // insert new layer and redraw map
                    Layers.Insert(0, newLayer);
                    redraw();
                };
                bw.ProgressChanged += (object wsender, ProgressChangedEventArgs we) =>
                {
                    //  update progress bar
                    if (we.ProgressPercentage < 0)
                    {
                        progressBar.Value = 0;
                        progressBar.Maximum = -we.ProgressPercentage;
                        progressLabel.Text = "Union - Second pass";
                    }
                    else
                        progressBar.Value += we.ProgressPercentage;
                };
                bw.RunWorkerAsync();
            });
            // reset default new layer name when selected layer is changed
            toolBuilder.resetAction = (Layer l) => {
                textbox.Text = (l == null) ? "" : l.Name + "_union";
            };
            toolBuilder.reset();
        }
Beispiel #4
0
        // buffer layer
        private void bufferButton_Click(object sender, EventArgs e)
        {
            toolBuilder.addHeader("Buffer");

            // textbox for buffer distance
            TextBox distBox = toolBuilder.addTextboxWithCaption("Distance (m):");
            // textbox for new layername
            TextBox nameBox = toolBuilder.addTextboxWithCaption("New layername:");
            // label for errors
            Label errorLabel = toolBuilder.addErrorLabel();

            // button for performing buffer
            Button selectButton = toolBuilder.addButton("Buffer", (Layer l) =>
            {
                double dist = 0;
                // buffer does not work on lat-long projections
                if (SRS.IsLatLong)
                {
                    toolBuilder.setError("Incompatible SRS");
                    return;
                }
                // distance must be a number
                if (!double.TryParse(distBox.Text, out dist))
                {
                    toolBuilder.setError("Not a number");
                    return;
                }
                // user must give new layer name
                if (nameBox.Text.Length == 0)
                {
                    toolBuilder.setError("Provide a name");
                    return;
                }

                // create new layer
                Layer newl = new Layer(nameBox.Text);
                newl.DataTable = l.DataTable;

                List<Feature> flist = l.Features.Values.ToList();

                // initialise progress bar
                progressLabel.Text = "Buffering";
                progressBar.Minimum = 0;
                progressBar.Maximum = flist.Count;

                // threadsafe list of new features
                ConcurrentBag<Feature> newFeatures = new ConcurrentBag<Feature>();

                BackgroundWorker bw = new BackgroundWorker();
                bw.WorkerReportsProgress = true;

                // perform buffering in other thread
                bw.DoWork += (object wsender, DoWorkEventArgs we) =>
                {
                    using (var finished = new CountdownEvent(1))
                    {
                        // for each feature
                        for (int i = 0; i < flist.Count; i++)
                        {
                            // add the task to buffer a feature to a thread pool
                            finished.AddCount();
                            Feature capture = flist[i];
                            ThreadPool.QueueUserWorkItem((state) =>
                            {
                                // get feature
                                Feature f = capture;
                                // add buffered feature
                                newFeatures.Add(new Feature(f.Geometry.Buffer(dist), f.ID));
                                bw.ReportProgress(i);
                                finished.Signal();
                            }, null);
                        }
                        finished.Signal();
                        finished.Wait();
                    }
                    bw.ReportProgress(-1);
                    // add all buffered features to layer
                    foreach(Feature f in newFeatures)
                    {
                        newl.addFeature(f);
                        bw.ReportProgress(1);
                    }
                    newl.calculateBoundingBox();
                    newl.createQuadTree();
                };
                bw.RunWorkerCompleted += (object wsender, RunWorkerCompletedEventArgs we) =>
                {
                    // reset progress bar
                    progressBar.Value = 0;
                    progressLabel.Text = "";

                    // add and zoom newly made layer
                    Layers.Insert(0, newl);
                    layerList.SelectedItem = newl;
                };
                bw.ProgressChanged += (object wsender, ProgressChangedEventArgs we) =>
                {
                    // update progress bar and progress label
                    if (we.ProgressPercentage == -1){
                        progressBar.Value = 0;
                        progressLabel.Text = "Creating spatial index";
                    }
                    else
                        progressBar.Value += 1;
                };
                bw.RunWorkerAsync();
            });

            toolBuilder.resetAction = (Layer l) =>
            {
                if (SRS.IsLatLong)
                    toolBuilder.setError("Incompatible SRS");
                nameBox.Text = (l == null) ? "" : l.Name + "_buffer";
            };

            toolBuilder.reset();
        }
Beispiel #5
0
        // merge two layers
        private void mergeButton_Click(object sender, EventArgs e)
        {
            toolBuilder.addHeader("Merge");
            // dropdown for selecting second layer
            ComboBox layerSelect = toolBuilder.addLayerSelect("Merge with:");
            // textbox for new layername
            TextBox textbox = toolBuilder.addTextboxWithCaption("New layername:");
            Label errorLabel = toolBuilder.addErrorLabel();
            // button for performing merge
            Button button = toolBuilder.addButton("Merge", (Layer l) =>
            {
                // no new layer name given
                if (textbox.Text.Length == 0)
                {
                    toolBuilder.setError("Provide name");
                    return;
                }
                Layer unionLayer = (Layer) layerSelect.SelectedItem;
                // layers must have same shapetype
                if (l.shapetype != unionLayer.shapetype)
                {
                    toolBuilder.setError("Incompatible types");
                    return;
                }
                // create new layer
                Layer newLayer = new Layer(textbox.Text);
                // create boundingbox as combination of two bb's
                newLayer.Boundingbox = new Envelope(l.Boundingbox);
                newLayer.Boundingbox.ExpandToInclude(unionLayer.Boundingbox);
                newLayer.createQuadTree();

                // add all features from one layer
                foreach (Feature f in l.Features.Values)
                    newLayer.addFeature(new Feature((IGeometry)f.Geometry.Clone()));
                // add all features from other layer
                foreach (Feature f in unionLayer.Features.Values)
                    newLayer.addFeature(new Feature((IGeometry)f.Geometry.Clone()));

                // insert newly made layer
                Layers.Insert(0, newLayer);
                // redraw map
                redraw();
            });
            // change default new layer name when selected layer changes
            toolBuilder.resetAction = (Layer l) =>
            {
                textbox.Text = (l == null) ? "" : l.Name + "_merge";
            };
            toolBuilder.reset();
        }
Beispiel #6
0
        // calculate intersection of layers
        private void intersectButton_Click(object sender, EventArgs e)
        {
            toolBuilder.addHeader("Intersect");
            // dropdown for selecting other layer
            ComboBox layerSelect = toolBuilder.addLayerSelect("Intersect with:");
            // textbox for new layer name
            TextBox textbox = toolBuilder.addTextboxWithCaption("New layername:");
            // laber for errors
            Label errorLabel = toolBuilder.addErrorLabel();
            //button for performing intersection
            Button button = toolBuilder.addButton("Intersect", (Layer l) =>
            {
                // new layer name not given
                if (textbox.Text.Length == 0)
                {
                    toolBuilder.setError("Provide name");
                    return;
                }
                Layer intersectLayer = (Layer)layerSelect.SelectedItem;
                Layer newLayer = new Layer(textbox.Text);

                // if both layers have attributes
                if (l.DataTable != null && intersectLayer.DataTable != null)
                {
                    // merge attributes, columnName collisions may be overwritten
                    DataTable a = l.DataTable.Clone();
                    newLayer.DataTable = intersectLayer.DataTable.Clone();
                    newLayer.DataTable.Merge(a, true, MissingSchemaAction.Add);
                }
                // if only one layer has attributes
                else if (l.DataTable != null && intersectLayer.DataTable == null)
                {
                    newLayer.DataTable = l.DataTable.Clone();
                }
                // if only the other layer has attributes
                else if (l.DataTable == null && intersectLayer.DataTable != null)
                {
                    newLayer.DataTable = intersectLayer.DataTable.Clone();
                }

                // init progress bar
                progressLabel.Text = "Intersection";
                progressBar.Minimum = 0;
                progressBar.Maximum = l.Features.Values.Count;

                // background worker for running in another thread
                BackgroundWorker bw = new BackgroundWorker();
                bw.WorkerReportsProgress = true;
                bw.DoWork += (object wsender, DoWorkEventArgs we) =>
                {
                    // loop through all features
                    for (int i = 0; i < l.Features.Count; i++ )
                    {
                        Feature f = l.Features.Values.ElementAt(i);
                        bw.ReportProgress(i);
                        // get intersecting features
                        var intersections = intersectLayer.getWithin(f.Geometry);
                        foreach (Feature intersect in intersections)
                        {
                            DataRow arow = l.getRow(f);
                            DataRow brow = intersectLayer.getRow(intersect);

                            // calculate intersection
                            Feature result = new Feature(f.Geometry.Intersection(intersect.Geometry));
                            int id = newLayer.addFeature(result);

                            // merge attributes
                            if (newLayer.DataTable != null)
                            {
                                DataRow dr = newLayer.DataTable.NewRow();
                                if (arow != null)
                                    foreach (DataColumn dc in arow.Table.Columns)
                                        dr[dc.ColumnName] = arow[dc.ColumnName];
                                if (brow != null)
                                    foreach (DataColumn dc in brow.Table.Columns)
                                        dr[dc.ColumnName] = brow[dc.ColumnName];
                                dr["sgis_id"] = id;
                                newLayer.DataTable.Rows.Add(dr);
                            }
                        }
                    }
                };
                bw.RunWorkerCompleted += (object wsender, RunWorkerCompletedEventArgs we) =>
                {
                    // reset progress bar
                    progressBar.Value = 0;
                    progressLabel.Text = "";

                    // finalise new layer
                    newLayer.calculateBoundingBox();
                    newLayer.createQuadTree();
                    Layers.Insert(0, newLayer);
                    redraw();
                };
                bw.ProgressChanged += (object wsender, ProgressChangedEventArgs we) =>
                {
                    // update progress bar
                    progressBar.Value = we.ProgressPercentage;
                };
                bw.RunWorkerAsync();
            });
            // reset new layer name
            toolBuilder.resetAction += (Layer l) =>
            {
                textbox.Text = (l == null) ? "" : l.Name + "_intersect";
            };
            toolBuilder.reset();
        }
Beispiel #7
0
        private void diffButton_Click(object sender, EventArgs e)
        {
            toolBuilder.addHeader("Difference");
            // dropdown for selecting other layer
            ComboBox layerSelect = toolBuilder.addLayerSelect("Layer to subtract:");
            // textbox for new layer name
            TextBox textbox = toolBuilder.addTextboxWithCaption("New layername:");
            // label for errors
            Label errorLabel = toolBuilder.addErrorLabel();
            // button for performing subtraction
            Button button = toolBuilder.addButton("Subtract", (Layer l) =>
            {
                // no new layer name is given
                if (textbox.Text.Length == 0)
                {
                    toolBuilder.setError("Provide name");
                    return;
                }
                // layers must have the same type of shapes
                Layer unionLayer = (Layer)layerSelect.SelectedItem;
                if (l.shapetype != unionLayer.shapetype)
                {
                    toolBuilder.setError("Incompatible types");
                    return;
                }
                Layer newLayer = new Layer(textbox.Text);
                newLayer.DataTable = l.DataTable;

                // init progress bar
                progressLabel.Text = "Subtracting";
                progressBar.Minimum = 0;
                progressBar.Maximum = l.Features.Values.Count;

                // background worker for running operation in another thread
                BackgroundWorker bw = new BackgroundWorker();
                bw.WorkerReportsProgress = true;
                bw.DoWork += (object wsender, DoWorkEventArgs we) =>
                {
                    // threadsafe list for storing new features
                    ConcurrentBag<Feature> newFeatures = new ConcurrentBag<Feature>();
                    using (var finished = new CountdownEvent(1))
                    {
                        foreach (Feature f in l.Features.Values)
                        {
                            finished.AddCount();
                            Feature capt = f;
                            // in each thread
                            ThreadPool.QueueUserWorkItem((state) =>
                            {
                                // clone feature
                                Feature newf = new Feature((IGeometry)capt.Geometry.Clone(), capt.ID);
                                // get intersecting features
                                var intersects = unionLayer.getWithin(capt.Geometry);
                                // subtract intersecting features
                                foreach (Feature intersect in intersects)
                                    newf.Geometry = newf.Geometry.Difference(intersect.Geometry);

                                // if there is something left of the original feature
                                if (!newf.Geometry.IsEmpty) // add it to new feature list
                                    newFeatures.Add(newf);
                                bw.ReportProgress(1);
                                finished.Signal();
                            }, null);
                        }
                        finished.Signal();
                        finished.Wait();
                    }
                    bw.ReportProgress(-newFeatures.Count);
                    // add all processed features to new layer
                    foreach (Feature f in newFeatures)
                    {
                        newLayer.addFeature(f);
                        bw.ReportProgress(1);
                    }
                };
                bw.RunWorkerCompleted += (object wsender, RunWorkerCompletedEventArgs we) =>
                {
                    // reset progressbar
                    progressBar.Value = 0;
                    progressLabel.Text = "";

                    // create quad tree and insert new layer
                    newLayer.calculateBoundingBox();
                    newLayer.createQuadTree();
                    Layers.Insert(0, newLayer);

                    redraw();
                };
                bw.ProgressChanged += (object wsender, ProgressChangedEventArgs we) =>
                {
                    // update progress bar
                    if (we.ProgressPercentage < 0)
                    {
                        progressBar.Value = 0;
                        progressBar.Maximum = -we.ProgressPercentage;
                        progressLabel.Text = "Creating spatial index";
                    }
                    else
                        progressBar.Value += we.ProgressPercentage;
                };
                bw.RunWorkerAsync();
            });
            // reset new layer name when selected layer changes
            toolBuilder.resetAction += (Layer l) =>
            {
                textbox.Text = (l == null) ? "" : l.Name + "_diff";
            };
            toolBuilder.reset();
        }