Я хочу построить график сворачивания РНК с помощью BGL, он имеет гарантированную плоскую структуру, и все ребра должны иметь одинаковую длину (есть два типа ребер: нормальная последовательность и связи, выделенные красным), например:
http://www.ncrna.org/frnadb/sec_structure/png/FR096703.png
namespace boost {
enum vertex_position_t { vertex_position };
BOOST_INSTALL_PROPERTY(vertex, position);
};
template<class PairIterator>
void layout(std::string seq, PairIterator begin, PairIterator end) {
using namespace boost; using namespace std;
// backbone edges + bonding edges
vector<pair<size_t,size_t>> edge_list(begin, end);
for(size_t i = 0 ; i < seq.size() - 1 ; i++)
edge_list.push_back(make_pair(i, i + 1));
typedef rectangle_topology<> topology;
typedef topology::point_type point;
boost::minstd_rand random;
topology space(random, -1000, -1000, 2000, 2000);
adjacency_list<vecS, vecS, undirectedS,
property<vertex_position_t, point>
> g(edge_list.begin(), edge_list.end(), seq.size());
random_graph_layout(g, get(vertex_position, g), space);
fruchterman_reingold_force_directed_layout(g, get(vertex_position, g), space,
cooling(linear_cooling<double>(100)));
// draw
}
Однако это дает мне очень случайную раскладку (для кулдауна 100, 200, 400). Более длительные кулдауны просто вдавливают вершины в углы (изображения показывают полный макет). Края кажутся постоянно слишком длинными...
Я хотел бы указать целевую длину для краев и не останавливать симуляцию, пока она не будет достигнута в пределах некоторого запаса.
Мой код собран из образцов повышения, но мне не нужно придерживаться карт свойств и т. д., я просто хочу макет, не прибегая к GraphViz.