BufferBuilder.cs :  » GIS » DeepEarth » GisSharpBlog » NetTopologySuite » Operation » Buffer » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » GIS » DeepEarth 
DeepEarth » GisSharpBlog » NetTopologySuite » Operation » Buffer » BufferBuilder.cs
using System.Collections;
using GeoAPI.Geometries;
using GeoAPI.Operations.Buffer;
using GisSharpBlog.NetTopologySuite.Algorithm;
using GisSharpBlog.NetTopologySuite.GeometriesGraph;
using GisSharpBlog.NetTopologySuite.Noding;
using GisSharpBlog.NetTopologySuite.Operation.Overlay;
using System.Collections.Generic;

namespace GisSharpBlog.NetTopologySuite.Operation.Buffer{
    /// <summary> 
    /// Builds the buffer point for a given input point and precision model.
    /// Allows setting the level of approximation for circular arcs,
    /// and the precision model in which to carry out the computation.
    /// When computing buffers in floating point double-precision
    /// it can happen that the process of iterated noding can fail to converge (terminate).
    /// In this case a TopologyException will be thrown.
    /// Retrying the computation in a fixed precision
    /// can produce more robust results.    
    /// </summary>
    public class BufferBuilder
    {
        /// <summary>
        /// Compute the change in depth as an edge is crossed from R to L.
        /// </summary>
        /// <param name="label"></param>
        private static int DepthDelta(Label label)
        {
            Locations lLoc = label.GetLocation(0, Positions.Left);
            Locations rLoc = label.GetLocation(0, Positions.Right);
            if (lLoc == Locations.Interior && rLoc == Locations.Exterior)
                return 1;
            else if (lLoc == Locations.Exterior && rLoc == Locations.Interior)
                return -1;
            return 0;
        }
        
        private int quadrantSegments = OffsetCurveBuilder.DefaultQuadrantSegments;
        private BufferStyle endCapStyle = BufferStyle.CapRound;
        
        private IPrecisionModel workingPrecisionModel = null;
        private INoder workingNoder = null;
        private IGeometryFactory geomFact = null;
        private PlanarGraph graph = null;
        private EdgeList edgeList = new EdgeList();        

        /// <summary>
        /// Gets/Sets the number of segments used to approximate a angle fillet.
        /// </summary>
        public int QuadrantSegments
        {
            get { return quadrantSegments;  }
            set { quadrantSegments = value; }
        }

        /// <summary>
        /// Gets/Sets the precision model to use during the curve computation and noding,
        /// if it is different to the precision model of the Geometry.
        /// If the precision model is less than the precision of the Geometry precision model,
        /// the Geometry must have previously been rounded to that precision.
        /// </summary>
        public IPrecisionModel WorkingPrecisionModel
        {
            get { return workingPrecisionModel;  }
            set { workingPrecisionModel = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public BufferStyle EndCapStyle
        {
            get { return endCapStyle;  }
            set { endCapStyle = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public INoder Noder
        {
            get { return workingNoder; }
            set { workingNoder = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="g"></param>
        /// <param name="distance"></param>
        /// <returns></returns>
        public IGeometry Buffer(IGeometry g, double distance)
        {
            IPrecisionModel precisionModel = workingPrecisionModel;
            if (precisionModel == null)
                precisionModel = g.PrecisionModel;

            // factory must be the same as the one used by the input
            geomFact = g.Factory;

            OffsetCurveBuilder curveBuilder = new OffsetCurveBuilder(precisionModel, quadrantSegments);
            curveBuilder.EndCapStyle = endCapStyle;
            OffsetCurveSetBuilder curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder);

            IList bufferSegStrList = curveSetBuilder.GetCurves();

            // short-circuit test
            if (bufferSegStrList.Count <= 0)
            {
                IGeometry emptyGeom = geomFact.CreateGeometryCollection(new IGeometry[0]);
                return emptyGeom;
            }

            ComputeNodedEdges(bufferSegStrList, precisionModel);
            graph = new PlanarGraph(new OverlayNodeFactory());
            graph.AddEdges(edgeList.Edges);

            IList subgraphList = CreateSubgraphs(graph);
            PolygonBuilder polyBuilder = new PolygonBuilder(geomFact);
            BuildSubgraphs(subgraphList, polyBuilder);
            IList resultPolyList = polyBuilder.Polygons;

            IGeometry resultGeom = geomFact.BuildGeometry(resultPolyList);
            return resultGeom;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="precisionModel"></param>
        /// <returns></returns>
        private INoder GetNoder(IPrecisionModel precisionModel)
        {
            if (workingNoder != null) 
                return workingNoder;

            // otherwise use a fast (but non-robust) noder
            LineIntersector li = new RobustLineIntersector();
            li.PrecisionModel = precisionModel;
            MCIndexNoder noder = new MCIndexNoder(new IntersectionAdder(li));                     
            return noder;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bufferSegStrList"></param>
        /// <param name="precisionModel"></param>
        private void ComputeNodedEdges(IList bufferSegStrList, IPrecisionModel precisionModel)
        {
            INoder noder = GetNoder(precisionModel);
            noder.ComputeNodes(bufferSegStrList);
            IList nodedSegStrings = noder.GetNodedSubstrings();
            
            foreach(object obj in nodedSegStrings)
            {
                SegmentString segStr = (SegmentString) obj;
                Label oldLabel = (Label) segStr.Data;
                Edge edge = new Edge(segStr.Coordinates, new Label(oldLabel));
                InsertEdge(edge);
            }
        }

        /// <summary>
        /// Inserted edges are checked to see if an identical edge already exists.
        /// If so, the edge is not inserted, but its label is merged
        /// with the existing edge.
        /// </summary>
        /// <param name="e"></param>
        protected void InsertEdge(Edge e)
        {
            //<FIX> MD 8 Oct 03  speed up identical edge lookup
            // fast lookup
            Edge existingEdge = edgeList.FindEqualEdge(e);

            // If an identical edge already exists, simply update its label
            if (existingEdge != null)
            {
                Label existingLabel = existingEdge.Label;

                Label labelToMerge = e.Label;
                // check if new edge is in reverse direction to existing edge
                // if so, must flip the label before merging it
                if (!existingEdge.IsPointwiseEqual(e))
                {
                    labelToMerge = new Label(e.Label);
                    labelToMerge.Flip();
                }
                existingLabel.Merge(labelToMerge);

                // compute new depth delta of sum of edges
                int mergeDelta = DepthDelta(labelToMerge);
                int existingDelta = existingEdge.DepthDelta;
                int newDelta = existingDelta + mergeDelta;
                existingEdge.DepthDelta = newDelta;
            }
            else
            {   // no matching existing edge was found
                // add this new edge to the list of edges in this graph
                //e.setName(name + edges.size());
                edgeList.Add(e);
                e.DepthDelta = DepthDelta(e.Label);
            }
        }

        private IList CreateSubgraphs(PlanarGraph graph)
        {
            var subgraphList = new List<BufferSubgraph>();
            foreach(object obj in graph.Nodes)
            {
                Node node = (Node)obj;
                if (!node.IsVisited)
                {
                    BufferSubgraph subgraph = new BufferSubgraph();
                    subgraph.Create(node);
                    subgraphList.Add(subgraph);
                }
            }

            /*
             * Sort the subgraphs in descending order of their rightmost coordinate.
             * This ensures that when the Polygons for the subgraphs are built,
             * subgraphs for shells will have been built before the subgraphs for
             * any holes they contain.
             */
            subgraphList.Sort();
            subgraphList.Reverse();
            return subgraphList;
        }

        /// <summary>
        /// Completes the building of the input subgraphs by depth-labelling them,
        /// and adds them to the <see cref="PolygonBuilder" />.
        /// The subgraph list must be sorted in rightmost-coordinate order.
        /// </summary>
        /// <param name="subgraphList">The subgraphs to build.</param>
        /// <param name="polyBuilder">The PolygonBuilder which will build the final polygons.</param>
        private void BuildSubgraphs(IList subgraphList, PolygonBuilder polyBuilder)
        {
            IList processedGraphs = new List<BufferSubgraph>();
            foreach(object obj in subgraphList)
            {
                BufferSubgraph subgraph = (BufferSubgraph)obj;
                ICoordinate p = subgraph.RightMostCoordinate;
                SubgraphDepthLocater locater = new SubgraphDepthLocater(processedGraphs);
                int outsideDepth = locater.GetDepth(p);
                subgraph.ComputeDepth(outsideDepth);
                subgraph.FindResultEdges();
                processedGraphs.Add(subgraph);
                polyBuilder.Add(subgraph.DirectedEdges, subgraph.Nodes);
            }
        }

    }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.