Files
2025-02-13 13:10:51 +02:00

124 lines
4.1 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "revng/GraphLayout/Graphs.h"
#include "revng/GraphLayout/SugiyamaStyle/InternalGraph.h"
namespace yield::layout::sugiyama {
/// Lists possible ranking strategies the layouter implements.
enum class RankingStrategy {
BreadthFirstSearch,
DepthFirstSearch,
Topological,
DisjointDepthFirstSearch
};
/// List graph orientation options the layouter implements.
enum class Orientation {
LeftToRight,
RightToLeft,
TopToBottom,
BottomToTop
};
struct Configuration {
public:
/// Specifies the way the layers of the graph are decided
RankingStrategy Ranking;
/// Specifies the orientation of the layout, (e.g. left-to-right):
/// The layers with lower ranks are closer to the first direction (e.g. left)
/// while those with higher ranks - to the second one (e.g. right).
Orientation Orientation;
/// Specifies whether orthogonal bending rules should be used, if not each
/// edge is just two points: its start and end.
bool UseOrthogonalBends;
/// Specifies whether linear segment preservation should be done.
///
/// This causes nodes any pair of nodes (A and B) such that A has only one
/// successor - B and B has only one predecessor - A to be always be routed
/// with a straight line (they both have the same horizontal position).
bool PreserveLinearSegments;
/// Specifies whether simple tree optimizations should be used.
///
/// A simple tree expects every single node to only have one predecessor and
/// to not have any back-edges.
bool UseSimpleTreeOptimization;
/// Specifies the "weight" of virtual nodes as opposed to the real ones.
///
/// Virtual nodes represent long edges (both forwards and backwards facing).
///
/// If weight is equal to 1, the placing of virtual nodes is identical to that
/// of the real ones.
///
/// If weight is bigger than 1 (e.g. 10), the virtual nodes are more likely
/// to be placed to the right of the layout (the bigger the weight, the more
/// noticeable its effect is).
///
/// If weight is smaller than 1 (e.g. 0.1), the virtual nodes are more likely
/// to be placed to the left of the layout (the smaller the weight, the more
/// noticeable its effect is).
///
/// \note: the layouts will be unnaturally skewed if this value is negative.
float VirtualNodeWeight;
/// Specifies the minimum possible distance between two nodes.
layout::Dimension NodeMarginSize;
/// Specifies the minimum possible distance between two edges.
layout::Dimension EdgeMarginSize;
};
namespace detail {
bool computeImpl(InternalGraph &Internal, const Configuration &Configuration);
} // namespace detail
template<layout::HasLayoutableGraphTraits GraphType>
inline bool
computeInPlace(GraphType &&Graph, const Configuration &Configuration) {
using IG = InternalGraph;
auto &&[Internal, InputNodeLookup] = IG::make(std::forward<GraphType>(Graph));
if (!detail::computeImpl(Internal, Configuration))
return false;
Internal.template exportInto<GraphType>(InputNodeLookup);
return true;
}
/// A custom graph layering algorithm designed for pre-calculating majority of
/// the expensive stuff needed for graph rendering.
///
/// \tparam Node The type of the data attached to each graph node
/// \tparam Edge The type of the data attached to each graph edge
///
/// \param Graph An input graph
/// \param Configuration An object configuring the specifics of the layout
///
/// \return The laid out version of the graph corresponding to \ref Graph
template<typename Node, typename Edge = Empty>
inline std::optional<layout::OutputGraph<Node, Edge>>
compute(const layout::InputGraph<Node, Edge> &Graph,
const Configuration &Configuration) {
// TODO: rename into `compute` once `llvm::GraphTraits` has a concept support
// for checking whether it's defined for a given type or not.
using OutputGraph = layout::OutputGraph<Node, Edge>;
std::optional<OutputGraph> Result = layout::detail::convert(Graph);
if (!computeInPlace(&Result.value(), Configuration))
Result = std::nullopt;
return Result;
}
} // namespace yield::layout::sugiyama