Node of the planar graph.
コード例 #1
0
ファイル: Overlays.cs プロジェクト: gkrsu/maparound.core
        private bool isNodeEnabled(PlanarGraphNode node, OverlayType operation, Polyline polyline, Polygon polygon, bool inverseArgs)
        {
            switch (operation)
            {
                case OverlayType.Intersection:
                    if (!node.Label.UsedByObject1 || !node.Label.UsedByObject2)
                        return false;
                    break;
                case OverlayType.Union:
                    return false;
                case OverlayType.Difference:
                case OverlayType.SymmetricDifference:
                    return false;
            }
            bool hasEnabledEdges = false;
            foreach (PlanarGraphEdge edge in node.IncidentEdges)
                if (isAreaEdgeEnabled(edge, operation, polygon, inverseArgs) ||
                    isLinearEdgeEnabled(edge, operation, polygon, inverseArgs))
                {
                    hasEnabledEdges = true;
                    break;
                }

            return !hasEnabledEdges;
        }
コード例 #2
0
ファイル: Topology.cs プロジェクト: gkrsu/maparound.core
        private void addOrMergeNode(ICoordinate coordinate, IGeometry obj)
        {
            double tolerance = PlanimetryAlgorithms.Tolerance;
            double x = coordinate.X;
            PlanarGraphNode node;

            int startIndex = 0, endIndex = _nodes.Count - 1;

            while (endIndex - startIndex > 1)
            {
                int index = startIndex + (endIndex - startIndex) / 2;
                if (_nodes[index].Point.X < x)
                    startIndex = index;
                else
                    endIndex = index;
            }

            while (startIndex > 0 &&
                   _nodes[startIndex].Point.X + tolerance > x)
                startIndex--;

            while (endIndex < _nodes.Count - 1 &&
                   _nodes[endIndex].Point.X - tolerance < x)
                endIndex++;

            for (int i = startIndex; i <= endIndex; i++)
            {
                ICoordinate p = _nodes[i].Point;

                if (Math.Abs(p.X - x) < tolerance &&
                    Math.Abs(p.Y - coordinate.Y) < tolerance)
                    if ((_performSnapping && p.ExactEquals(coordinate)) ||
                        (!_performSnapping && p.Equals(coordinate)))
                    {
                        _nodes[i].Label.UsedByObject1 = obj == _sourceGeometry1 || _nodes[i].Label.UsedByObject1;
                        _nodes[i].Label.UsedByObject2 = obj == _sourceGeometry2 || _nodes[i].Label.UsedByObject2;
                        return;
                    }

                if (p.X > x)
                {
                    node = new PlanarGraphNode(coordinate);
                    node.Label.UsedByObject1 = obj == _sourceGeometry1;
                    node.Label.UsedByObject2 = obj == _sourceGeometry2;

                    if(obj == _sourceGeometry1)
                        node.Label.Object1OccurrencesCount++;

                    if(obj == _sourceGeometry2)
                        node.Label.Object2OccurrencesCount++;

                    _nodes.Insert(i, node);
                    return;
                }
            }

            node = new PlanarGraphNode(coordinate);
            node.Label.UsedByObject1 = obj == _sourceGeometry1;
            node.Label.UsedByObject2 = obj == _sourceGeometry2;

            if (obj == _sourceGeometry1)
                node.Label.Object1OccurrencesCount++;

            if (obj == _sourceGeometry2)
                node.Label.Object2OccurrencesCount++;

            _nodes.Add(node);
        }
コード例 #3
0
ファイル: Topology.cs プロジェクト: gkrsu/maparound.core
 /// <summary>
 /// Swap nodes of edges.
 /// </summary>
 internal void SwapNodes()
 {
     PlanarGraphNode node = _node1;
     _node1 = _node2;
     _node2 = node;
 }
コード例 #4
0
ファイル: Topology.cs プロジェクト: gkrsu/maparound.core
 /// <summary>
 /// Initializes a new instance of MapAround.Geometry.PlanarGraphEdge
 /// </summary>
 /// <param name="node1">First node</param>
 /// <param name="node2">Second node</param>
 public PlanarGraphEdge(PlanarGraphNode node1, PlanarGraphNode node2)
 {
     _node1 = node1;
     _node2 = node2;
 }
コード例 #5
0
ファイル: Topology.cs プロジェクト: gkrsu/maparound.core
        /// <summary>
        /// Constructs a contour.
        /// </summary>
        private Contour processContour(int startNodeIndex,
                                       PlanarGraphNode.NodeLayout layout,
                                       bool markObject1EdgesOrientation,
                                       bool markObject2EdgesOrientation)
        {
            Contour result = null;

            PlanarGraphNode startNode = _nodes[startNodeIndex];
            for (int j = 0; j < startNode.IncidentEdges.Count; j++)
            {
                if (!startNode.IncidentEdges[j].IsVisited &&
                    startNode.IncidentEdges[j].Enabled) // инцидентное ребро не пройдено
                {
                    if (result == null)
                        result = new Contour();

                    result.Vertices.Add((ICoordinate)startNode.Point.Clone()); // первая вершина нового контура

                    PlanarGraphNode currentNode = startNode;

                    Segment previousEdge = new Segment();
                    bool edgeDetected = false;

                    List<PlanarGraphEdge> possibleEdges = new List<PlanarGraphEdge>();

                    while (true)
                    {
                        // определение ребра для поворота направо (налево для дырки)
                        possibleEdges.Clear();

                        foreach (PlanarGraphEdge edge in currentNode.IncidentEdges)
                            if (!edge.IsVisited && edge.Enabled)
                                possibleEdges.Add(edge);

                        if (possibleEdges.Count > 0)
                        {
                            if (!edgeDetected)
                            {
                                previousEdge.V1 = (ICoordinate)currentNode.Point.Clone();
                                previousEdge.V2 = (ICoordinate)currentNode.Point.Clone();

                                double l = PlanimetryAlgorithms.Tolerance * 1e10;

                                if (layout == PlanarGraphNode.NodeLayout.Internal) // для 1-го ребра должен определяться угол с вертикалью
                                    previousEdge.V2.Y -= l;
                                else
                                    previousEdge.V2.Y += l;

                                edgeDetected = true;
                            }

                            double maxAngle = 0; // максимальный найденный угол поворота
                            double minAngle = _twoPi; // минимальный найденный угол поворота
                            PlanarGraphEdge targetEdge = null; // целевое ребро

                            if (possibleEdges.Count == 1)
                                targetEdge = possibleEdges[0];
                            else
                            {
                                for (int k = 0; k < possibleEdges.Count; k++) // находим ребро с минимальным углом
                                {
                                    PlanarGraphEdge edge = possibleEdges[k];
                                    Segment kEdge = new Segment(edge.Node1.Point, edge.Node2.Point);
                                    double angle;
                                    try
                                    {
                                        if (result.Vertices.Count < 2)
                                            angle = Math.Min(getAngleBetweenEdges(ref previousEdge, ref kEdge, true),
                                                             getAngleBetweenEdges(ref previousEdge, ref kEdge, false));
                                        else
                                            angle = getAngleBetweenEdges(ref previousEdge, ref kEdge, layout == PlanarGraphNode.NodeLayout.Internal);
                                    }
                                    catch (ArgumentException)
                                    {
                                        throw new TopologyException();
                                    }

                                    if (angle >= _twoPi)
                                        angle -= _twoPi;

                                    if (result.Vertices.Count > 1)
                                    {
                                        if (angle > maxAngle)
                                        {
                                            maxAngle = angle;
                                            targetEdge = edge;
                                        }
                                    }
                                    else // первое ребро - особый случай, ищем минимальный угол
                                    {
                                        if (angle < minAngle)
                                        {
                                            minAngle = angle;
                                            targetEdge = edge;
                                        }
                                    }
                                }
                            }

                            if (targetEdge != null)
                            {
                                if (targetEdge.Node1.Point.ExactEquals(currentNode.Point))
                                {
                                    if (markObject1EdgesOrientation)
                                            targetEdge.OrientationInObject1 = PlanarGraphEdge.EdgeOrientation.Forward;

                                    if (markObject2EdgesOrientation)
                                            targetEdge.OrientationInObject2 = PlanarGraphEdge.EdgeOrientation.Forward;

                                    result.Vertices.Add((ICoordinate)targetEdge.Node2.Point.Clone());
                                    targetEdge.Node2.Layout = layout;
                                    currentNode = targetEdge.Node2;
                                }
                                else
                                {
                                    if (markObject1EdgesOrientation)
                                            targetEdge.OrientationInObject1 = PlanarGraphEdge.EdgeOrientation.Backward;

                                    if (markObject2EdgesOrientation)
                                            targetEdge.OrientationInObject2 = PlanarGraphEdge.EdgeOrientation.Backward;

                                    result.Vertices.Add((ICoordinate)targetEdge.Node1.Point.Clone());
                                    targetEdge.Node1.Layout = layout;
                                    currentNode = targetEdge.Node1;
                                }

                                previousEdge = new Segment(targetEdge.Node1.Point, targetEdge.Node2.Point);
                                targetEdge.IsVisited = true;

                                if (currentNode == startNode) // пришли, контур сформирован
                                {
                                    result.Vertices.RemoveAt(result.Vertices.Count - 1);
                                    break;
                                }
                            }
                            else
                                break;
                        }
                        else
                        {
                            // по какой-то причине контур не может быть завершен
                            throw new TopologyException();
                        }
                    }
                    break;
                }
            }

            return result;
        }