Exemplo n.º 1
0
        // adds feature to node
        public void add(Feature f)
        {
            // if node is leaf node and has less than 20 features
            if (!hasChildren && features.Count < 20)
            {
                features.Add(f);
                f.Parent = this;
                return;
            }

            // if node is leaf node and has more than 19 children
            if (!hasChildren)
                split();    // split node and divide features

            foreach (QuadTree qt in children)
            {
                // if child completely contains feature
                if (qt.gboundary.Contains(f.Geometry))
                {
                    qt.add(f);
                    return;
                }
            }
            // if feature spans multiple children
            features.Add(f);
            f.Parent = this;
        }
Exemplo n.º 2
0
        private void readShape()
        {
            // read shape id, data length and shape type
            int id = br.ReadInt32BigEndian();
            int length = br.ReadInt32BigEndian();
            int stype = br.ReadInt32();
            pos += 12;

            if (stype == 0) // Null
                return;
            Geometry g = null;
            if (stype == 1) // Point
                g = readPoint();
            if (stype == 3) // Polyline
                g = readPolyline();
            if (stype == 5) // Polygon
                g = readPolygon();

            // add shape to layer
            if (g != null)
            {
                Feature f = new Feature(g, id);
                layer.addFeature(f);
            }
        }
Exemplo n.º 3
0
Arquivo: Layer.cs Projeto: hakbra/SGIS
 // returns attributes for feature in layer
 public DataRow getRow(Feature f)
 {
     if (DataTable == null)
         return null;
     return DataTable.Rows[f.ID - 1];
 }
Exemplo n.º 4
0
Arquivo: Layer.cs Projeto: hakbra/SGIS
 // delete feature to layer
 public void delFeature(Feature s)
 {
     if (s.Selected)
         Selected.Remove(s);
     if (s.Parent != null)
         s.Parent.remove(s);
     Features.Remove(s.ID);
 }
Exemplo n.º 5
0
Arquivo: Layer.cs Projeto: hakbra/SGIS
        // adds feature to layer
        public int addFeature(Feature s)
        {
            // checks for correct shapetype
            // a layer may only contain shapes of one type
            if (shapetype == ShapeType.EMPTY)
            {
                shapetype = convert(s.Geometry.GeometryType);
                if (shapetype == ShapeType.POINT) // default to black color for points
                    Style.brush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
            }
            else if (shapetype != convert(s.Geometry.GeometryType))
                throw new Exception("Wrong shapetype in layer " + name);

            // assigns id to feature
            if (s.ID > maxid)
                maxid = s.ID + 1;
            if (s.ID == -1)
                s.ID = maxid++;
            Features.Add(s.ID, s);
            if (QuadTree != null)
                QuadTree.add(s);
            return s.ID;
        }
Exemplo n.º 6
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();
        }
Exemplo n.º 7
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();
        }
Exemplo n.º 8
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();
        }
Exemplo n.º 9
0
 public void remove(Feature f)
 {
     features.Remove(f);
 }