Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://github.com/GTMeijer/TIN_Viewsheds
03 July 2026, 12:54:31 UTC
  • Code
  • Branches (1)
  • Releases (0)
  • Visits
    • Branches
    • Releases
    • HEAD
    • refs/heads/main
    • 3228d926579e0631b255e7478f24963a508637b4
    No releases to show
  • 911b845
  • /
  • ViewshedRelationGraph.cpp
Raw File Download Save again
Take a new snapshot of a software origin

If the archived software origin currently browsed is not synchronized with its upstream version (for instance when new commits have been issued), you can explicitly request Software Heritage to take a new snapshot of it.

Use the form below to proceed. Once a request has been submitted and accepted, it will be processed as soon as possible. You can then check its processing state by visiting this dedicated page.
swh spinner

Processing "take a new snapshot" request ...

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
origin badgecontent badge
swh:1:cnt:105d413343d0624250cc43898df28818b74bd357
origin badgedirectory badge
swh:1:dir:911b84528046c62ddd56c32905926748dd59791e
origin badgerevision badge
swh:1:rev:3228d926579e0631b255e7478f24963a508637b4
origin badgesnapshot badge
swh:1:snp:a61033758c7e06cfb67229206ddb2d2cfad7abd7

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
Tip revision: 3228d926579e0631b255e7478f24963a508637b4 authored by Gert Meijer on 06 May 2021, 03:42:18 UTC
Base code files push
Tip revision: 3228d92
ViewshedRelationGraph.cpp
#include "precomp.h"
#include "ViewshedRelationGraph.h"


namespace Viewshed
{
    ViewshedRelationGraph::ViewshedRelationGraph(const std::vector<VSRelationEdge>& relationEdges)
    {
        AddEdges(relationEdges);
    }

    void ViewshedRelationGraph::AddEdges(const std::vector<VSRelationEdge>& relationEdges)
    {
        for (const VSRelationEdge& re : relationEdges)
        {
            AddEdge(re);
        }
    }

    void ViewshedRelationGraph::AddEdge(const VSRelationEdge& relationEdge)
    {
        assert(relationEdge.iSource >= 0);
        assert(relationEdge.jDestination >= 0);
        assert(!(relationEdge.obscured && relationEdge.obscures));

        //Add twin of obscures as well (Handles embedded polys)
        //TODO: Improve this, map of maps instead?
        if (relationEdge.obscures)
        {
            VSRelationEdge twinEdge(relationEdge.jDestination, relationEdge.iSource);
            twinEdge.obscured = true;
            twinEdge.intersects = relationEdge.intersects;
            AddEdge(twinEdge);
        }

        nodes[relationEdge.iSource].push_back(relationEdge);
    }

    void ViewshedRelationGraph::AddNode(const int node)
    {
        nodes.insert(std::pair<int, std::vector<VSRelationEdge>>(node, std::vector<VSRelationEdge>()));
    }

    void ViewshedRelationGraph::RemoveNode(const int node)
    {
        nodes.erase(node);
    }

    void ViewshedRelationGraph::RemoveNodes(const std::vector<int> nodes)
    {
        for (const int n : nodes)
        {
            RemoveNode(n);
        }
    }

    //Removes all edges that contain a destination to a node that does not exist in the graph
    void ViewshedRelationGraph::Trim()
    {
        for (auto& node : nodes)
        {
            node.second.erase(std::remove_if(node.second.begin(), node.second.end(), [&](VSRelationEdge edge) {return (nodes.find(edge.jDestination) == nodes.end()); }), node.second.end());
        }
    }

    //Removes all edges that represent an intersection between two polygons
    void ViewshedRelationGraph::RemoveIntersectionEdges()
    {
        for (auto& node : nodes)
        {
            node.second.erase(std::remove_if(node.second.begin(), node.second.end(), [&](VSRelationEdge edge) {return (edge.intersects); }), node.second.end());
        }
    }

    std::vector<VSRelationEdge> ViewshedRelationGraph::GetEdges(const int nodeId) const
    {
        return nodes.at(nodeId);
    }

    //Returns the closest neighbouring node based on a given priority list (Far -> Close)
    int ViewshedRelationGraph::GetClosestNeighbour(const int nodeId, const std::vector<int>& priorities) const
    {
        int highestPrio = -1;
        int highestindex = -1;
        for (const VSRelationEdge& edge : nodes.at(nodeId))
        {
            std::vector<int>::const_iterator it = std::find(priorities.begin(), priorities.end(), edge.jDestination);

            if (it != priorities.end())
            {
                int index = std::distance(priorities.begin(), it);
                if (index > highestindex)
                {
                    highestPrio = priorities.at(index);
                    highestindex = index;
                }
            }
        }

        return highestPrio;
    }

    std::vector<int> ViewshedRelationGraph::GetStartingNodes() const
    {
        std::vector<int> startNodes;
        for (auto& node : nodes)
        {
            //If node does not have any 'obscures' edges add to start node list
            bool obscures = false;
            for (const VSRelationEdge& edge : node.second)
            {
                obscures = (obscures || edge.obscures);
            }

            if (!obscures)
            {
                startNodes.push_back(node.first);
            }
        }

        return startNodes;
    }

    //Sorts the nodes in the graph from farthest to closest polygons
    std::vector<int> ViewshedRelationGraph::TopologicalSort() const
    {
        std::vector<int> sortedNodes;
        sortedNodes.reserve(nodes.size());

        //For each node set visited to false
        std::map<int, bool> visited;
        for (auto& n : nodes)
        {
            visited[n.first] = false;
        }

        //For each starting node recursively visit the graph depth first
        std::vector<int> visitStack = GetStartingNodes();
        while (!visitStack.empty())
        {
            TopologicalSortVisit(visitStack.back(), sortedNodes, visited);
            visitStack.pop_back();
        }

        //Reverse the order of the sorted vector and return
        std::reverse(sortedNodes.begin(), sortedNodes.end());
        return sortedNodes;
    }

    void ViewshedRelationGraph::TopologicalSortVisit(const int node, std::vector<int>& sortedNodes, std::map<int, bool>& visited) const
    {
        if (visited.at(node))
        {
            return;
        }

        //Recursively visit each child node that obscures this nodes polygon
        for (const VSRelationEdge& edge : nodes.at(node))
        {
            if (edge.obscured)
            {
                TopologicalSortVisit(edge.jDestination, sortedNodes, visited);
            }
        }

        //After visiting each child mark as visited and add this node to the sorted list
        visited.at(node) = true;
        sortedNodes.push_back(node);
    }

    void ViewshedRelationGraph::PrintGraph() const
    {
        std::cout << "Overlap relation graph:" << std::endl;
        for (auto& node : nodes)
        {
            std::cout << node.first << std::endl;


            for (auto& edge : node.second)
            {
                if (edge.obscures)
                {
                    std::cout << "\t" << edge.iSource << "<" << edge.jDestination;
                }

                if (edge.obscured)
                {
                    std::cout << "\t" << edge.iSource << ">" << edge.jDestination;
                }

                if (!edge.intersects)
                {
                    std::cout << "(embedded)";
                }

                std::cout << std::endl;
            }
        }
    }
}

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API