diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/3rdparty/adaptagrams/libcola | |
parent | Initial commit. (diff) | |
download | inkscape-upstream/1.2.2.tar.xz inkscape-upstream/1.2.2.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/3rdparty/adaptagrams/libcola')
82 files changed, 51253 insertions, 0 deletions
diff --git a/src/3rdparty/adaptagrams/libcola/CMakeLists.txt b/src/3rdparty/adaptagrams/libcola/CMakeLists.txt new file mode 100644 index 0000000..59bbacc --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/CMakeLists.txt @@ -0,0 +1,30 @@ + +set(libcola_SRC + box.cpp + cluster.cpp + cola.cpp + convex_hull.cpp + compound_constraints.cpp + conjugate_gradient.cpp + connected_components.cpp + gradient_projection.cpp + shapepair.cpp + straightener.cpp + + + # ------- + # Headers + box.h + cluster.h + cola.h + compound_constraints.h + conjugate_gradient.h + convex_hull.h + gradient_projection.h + shapepair.cpp + shortest_paths.h + straightener.h +) + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/..") +add_inkscape_lib(cola_LIB "${libcola_SRC}") diff --git a/src/3rdparty/adaptagrams/libcola/Makefile.am b/src/3rdparty/adaptagrams/libcola/Makefile.am new file mode 100644 index 0000000..e35f7ae --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/Makefile.am @@ -0,0 +1,60 @@ +EXTRA_DIST=libcola.pc.in + +lib_LTLIBRARIES = libcola.la +libcola_la_CPPFLAGS = -I$(top_srcdir) $(CAIROMM_CFLAGS) -I$(includedir)/libcola -fPIC + +# Depends on libvpsc +libcola_la_LIBADD = $(top_builddir)/libvpsc/libvpsc.la $(CAIROMM_LIBS) + +libcola_la_SOURCES = cola.h\ + cola.cpp\ + colafd.cpp\ + conjugate_gradient.cpp\ + conjugate_gradient.h\ + exceptions.h\ + gradient_projection.cpp\ + gradient_projection.h\ + shortest_paths.h\ + straightener.h\ + straightener.cpp\ + connected_components.cpp\ + convex_hull.h\ + convex_hull.cpp\ + cluster.cpp\ + compound_constraints.h\ + compound_constraints.cpp\ + pseudorandom.h \ + pseudorandom.cpp \ + output_svg.cpp\ + output_svg.h \ + unused.h \ + cc_clustercontainmentconstraints.cpp \ + cc_clustercontainmentconstraints.h \ + cc_nonoverlapconstraints.cpp \ + cc_nonoverlapconstraints.h \ + box.cpp \ + box.h \ + shapepair.cpp \ + shapepainr.h + +libcolaincludedir = $(includedir)/libcola +libcolainclude_HEADERS = cola.h\ + cluster.h\ + commondefs.h\ + compound_constraints.h\ + pseudorandom.h \ + exceptions.h\ + gradient_projection.h\ + sparse_matrix.h\ + straightener.h \ + output_svg.h \ + unused.h \ + cc_clustercontainmentconstraints.h \ + cc_nonoverlapconstraints.h \ + box.h \ + shapepair.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libcola.pc + +SUBDIRS = . tests diff --git a/src/3rdparty/adaptagrams/libcola/box.cpp b/src/3rdparty/adaptagrams/libcola/box.cpp new file mode 100644 index 0000000..8ad3cba --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/box.cpp @@ -0,0 +1,111 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#include "libcola/box.h" + +namespace cola { + +Box::Box(double xMin, double xMax, double yMin, double yMax) +{ + m_min[vpsc::XDIM] = nonNegative(xMin); + m_max[vpsc::XDIM] = nonNegative(xMax); + m_min[vpsc::YDIM] = nonNegative(yMin); + m_max[vpsc::YDIM] = nonNegative(yMax); +} + +Box::Box(double all) +{ + double value = nonNegative(all); + m_min[vpsc::XDIM] = value; + m_max[vpsc::XDIM] = value; + m_min[vpsc::YDIM] = value; + m_max[vpsc::YDIM] = value; +} + +Box::Box() +{ + m_min[vpsc::XDIM] = 0; + m_max[vpsc::XDIM] = 0; + m_min[vpsc::YDIM] = 0; + m_max[vpsc::YDIM] = 0; +} + +Box::~Box() +{ +} + +bool Box::empty(void) const +{ + // values will be nonnegative so can sum to check if empty. + int total = m_min[vpsc::XDIM] + m_max[vpsc::XDIM] + + m_min[vpsc::YDIM] + m_max[vpsc::YDIM]; + return (total == 0); +} + +void Box::outputCode(FILE *fp) const +{ + if ((m_min[vpsc::XDIM] == m_max[vpsc::XDIM]) && + (m_min[vpsc::XDIM] == m_min[vpsc::YDIM]) && + (m_min[vpsc::XDIM] == m_max[vpsc::YDIM])) + { + fprintf(fp, "Box(%g)", m_min[vpsc::XDIM]); + } + else + { + fprintf(fp, "Box(%g, %g, %g, %g)", m_min[vpsc::XDIM], + m_max[vpsc::XDIM], m_min[vpsc::YDIM], m_max[vpsc::YDIM]); + } +} + +vpsc::Rectangle Box::rectangleByApplyingBox( + const vpsc::Rectangle rectangle) const +{ + if (!rectangle.isValid()) + { + return rectangle; + } + + return vpsc::Rectangle( + rectangle.getMinX() - m_min[vpsc::XDIM], + rectangle.getMaxX() + m_max[vpsc::XDIM], + rectangle.getMinY() - m_min[vpsc::YDIM], + rectangle.getMaxY() + m_max[vpsc::YDIM]); +} + +double Box::nonNegative(double value) +{ + return (value >= 0) ? value: 0; +} + +double Box::min(size_t dim) const +{ + return (dim < 2) ? m_min[dim] : 0; +} + +double Box::max(size_t dim) const +{ + return (dim < 2) ? m_max[dim] : 0; +} + + +} + diff --git a/src/3rdparty/adaptagrams/libcola/box.h b/src/3rdparty/adaptagrams/libcola/box.h new file mode 100644 index 0000000..ff8f018 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/box.h @@ -0,0 +1,82 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#ifndef LIBCOLA_BOX_H +#define LIBCOLA_BOX_H + +#include <cstdio> + +#include "libvpsc/rectangle.h" + + +namespace cola { + +/** + * @brief A box consisting of four edge values for representing padding or + * margins for rectangles. + */ +class Box +{ + public: + /** + * @brief Constructs a padding or margin box consisting of a value for + * each edge. + * + * Values should be nonnegative. + * + * @param[in] xMin Minimum horizontal value. + * @param[in] xMax Maximum horizontal value. + * @param[in] yMin Minimum vertical value. + * @param[in] yMax Maximum vertical value. + */ + Box(double xMin, double xMax, double yMin, double yMax); + /** + * @brief Constructs a padding or margin box consisting of a value for + * each edge. + * + * Values should be nonnegative. + * + * @param[in] all The value to be used for all four edges. + */ + Box(double all); + /** + * @brief Constructs an empty padding or margin box. + */ + Box(); + ~Box(); + + bool empty(void) const; + double min(size_t dim) const; + double max(size_t dim) const; + void outputCode(FILE *fp) const; + vpsc::Rectangle rectangleByApplyingBox( + const vpsc::Rectangle rectangle) const; + + private: + static double nonNegative(double value); + + double m_min[2]; + double m_max[2]; +}; + +} // namespace cola +#endif diff --git a/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.cpp b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.cpp new file mode 100644 index 0000000..390f5e1 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.cpp @@ -0,0 +1,194 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2010 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#include <sstream> + +#include "libcola/cola.h" +#include "libcola/compound_constraints.h" +#include "libcola/cc_clustercontainmentconstraints.h" + +using vpsc::XDIM; +using vpsc::YDIM; + + +namespace cola { + +static const int AboveBoundary = 1; +static const int BelowBoundary = -1; + +class ClusterShapeOffsets : public SubConstraintInfo +{ + public: + ClusterShapeOffsets(unsigned ind, vpsc::Dim dim, double offset, int boundarySide, + unsigned int boundaryVar) : + SubConstraintInfo(ind), + offset(offset), + dim(dim), + boundarySide(boundarySide), + boundaryVar(boundaryVar) + { + } + double offset; // half the width or height value + vpsc::Dim dim; // The dimension + int boundarySide; // The boundary side we are constraining on. + unsigned int boundaryVar; // The boundary var. +}; + + +ClusterContainmentConstraints::ClusterContainmentConstraints(Cluster *cluster, + unsigned int priority, std::vector<vpsc::Rectangle*>& boundingBoxes) + : CompoundConstraint(vpsc::HORIZONTAL, priority) +{ + Box padding = cluster->padding(); + _combineSubConstraints = true; + for (std::set<unsigned>::iterator curr = cluster->nodes.begin(); + curr != cluster->nodes.end(); ++curr) + { + unsigned id = *curr; + double halfW = (boundingBoxes[id]->width() / 2.0); + double halfH = (boundingBoxes[id]->height() / 2.0); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + id, XDIM, halfW + padding.min(XDIM), AboveBoundary, + cluster->clusterVarId)); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + id, XDIM, halfW + padding.max(XDIM), BelowBoundary, + cluster->clusterVarId + 1)); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + id, YDIM, halfH + padding.min(YDIM), AboveBoundary, + cluster->clusterVarId)); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + id, YDIM, halfH + padding.max(YDIM), BelowBoundary, + cluster->clusterVarId + 1)); + } + for (std::vector<Cluster *>::iterator curr = cluster->clusters.begin(); + curr != cluster->clusters.end(); ++curr) + { + Cluster *childCluster = *curr; + Box margin = childCluster->margin(); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + childCluster->clusterVarId, XDIM, + padding.min(XDIM) + margin.min(XDIM), AboveBoundary, + cluster->clusterVarId)); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + childCluster->clusterVarId + 1, XDIM, + padding.max(XDIM) + margin.max(XDIM), BelowBoundary, + cluster->clusterVarId + 1)); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + childCluster->clusterVarId, YDIM, + padding.min(YDIM) + margin.min(YDIM), AboveBoundary, + cluster->clusterVarId)); + _subConstraintInfo.push_back(new ClusterShapeOffsets( + childCluster->clusterVarId + 1, YDIM, + padding.max(YDIM) + margin.max(YDIM), BelowBoundary, + cluster->clusterVarId + 1)); + } +} + + +std::string ClusterContainmentConstraints::toString(void) const +{ + std::ostringstream stream; + stream << "ClusterContainmentConstraints()"; + return stream.str(); +} + + +void ClusterContainmentConstraints::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + COLA_UNUSED(dim); + COLA_UNUSED(vars); +} + + + +SubConstraintAlternatives +ClusterContainmentConstraints::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + SubConstraintAlternatives alternatives; + + ClusterShapeOffsets *info = static_cast<ClusterShapeOffsets *> + (_subConstraintInfo[_currSubConstraintIndex]); + + assertValidVariableIndex(vs[_primaryDim], info->varIndex); + if (info->boundarySide == BelowBoundary) + { + // Constrain the objects with negative offsets to be + // to the left of the boundary. + vpsc::Constraint constraint = vpsc::Constraint( + vs[info->dim][info->varIndex], vs[info->dim][info->boundaryVar], + info->offset); + alternatives.push_back(SubConstraint(info->dim, constraint)); + } + else + { + // Constrain the objects with positive offsets to be + // to the right of the boundary. + vpsc::Constraint constraint = vpsc::Constraint( + vs[info->dim][info->boundaryVar], vs[info->dim][info->varIndex], + info->offset); + alternatives.push_back(SubConstraint(info->dim, constraint)); + } + + //fprintf(stderr, "===== BOUNDARYLINE ALTERNATIVES -======\n"); + return alternatives; +} + + +void ClusterContainmentConstraints::generateSeparationConstraints( + const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs, + std::vector<vpsc::Rectangle*>& bbs) +{ + COLA_UNUSED(bbs); + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + ClusterShapeOffsets *info = static_cast<ClusterShapeOffsets *> (*o); + + if (info->dim != dim) + { + continue; + } + + vpsc::Constraint *constraint = nullptr; + if (info->boundarySide == BelowBoundary) + { + // Constrain the objects with negative offsets to be + // to the left of the boundary. + constraint = new vpsc::Constraint(vs[info->varIndex], + vs[info->boundaryVar], info->offset); + } + else + { + // Constrain the objects with positive offsets to be + // to the right of the boundary. + constraint = new vpsc::Constraint(vs[info->boundaryVar], + vs[info->varIndex], info->offset); + } + constraint->creator = this; + cs.push_back(constraint); + } +} + + +} // namespace cola + diff --git a/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.h b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.h new file mode 100644 index 0000000..5fbe75e --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.h @@ -0,0 +1,52 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2010 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#ifndef COLA_CC_CLUSTERCONTAINMENTCONSTRAINTS_H +#define COLA_CC_CLUSTERCONTAINMENTCONSTRAINTS_H + +#include <vector> +#include "libcola/compound_constraints.h" + +namespace vpsc { +class Rectangle; +} + +namespace cola { + +class ClusterContainmentConstraints : public CompoundConstraint +{ + public: + ClusterContainmentConstraints(Cluster *cluster, unsigned int priority, + std::vector<vpsc::Rectangle*>& boundingBoxes); + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& cs, + std::vector<vpsc::Rectangle*>& bbs); + std::string toString(void) const; +}; + + +} // namespace cola +#endif // COLA_CC_CLUSTERCONTAINMENTCONSTRAINTS diff --git a/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.cpp b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.cpp new file mode 100644 index 0000000..69502d0 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.cpp @@ -0,0 +1,590 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2010-2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#include <sstream> + +#include "libcola/cola.h" +#include "libcola/compound_constraints.h" +#include "libcola/cc_nonoverlapconstraints.h" + +using vpsc::XDIM; +using vpsc::YDIM; + + +namespace cola { + +//----------------------------------------------------------------------------- +// NonOverlapConstraintExemptions code +//----------------------------------------------------------------------------- + +NonOverlapConstraintExemptions::NonOverlapConstraintExemptions() +{ +} + +void NonOverlapConstraintExemptions::addExemptGroupOfNodes( + ListOfNodeIndexes listOfNodeGroups) +{ + m_exempt_pairs.clear(); + + const size_t listSize = listOfNodeGroups.size(); + for (size_t l = 0; l < listSize; ++l) + { + NodeIndexes ids(listOfNodeGroups[l]); + + // Sort and remove duplicate IDs for this group. + std::sort(ids.begin(), ids.end()); + NodeIndexes::iterator last = std::unique(ids.begin(), ids.end()); + ids.erase(last, ids.end()); + + // Add all combinations of pairs of IDs for this group to m_exempt_pairs + const size_t idsSize = ids.size(); + for (size_t i = 0; i < idsSize; ++i) + { + for (size_t j = i + 1; j < idsSize; ++j) + { + m_exempt_pairs.insert(ShapePair(ids[i], ids[j])); + } + } + + } +} + +bool NonOverlapConstraintExemptions::shapePairIsExempt( + ShapePair shapePair) const +{ + return (m_exempt_pairs.count(shapePair) == 1); +} + +//----------------------------------------------------------------------------- +// NonOverlapConstraints code +//----------------------------------------------------------------------------- + +NonOverlapConstraints::NonOverlapConstraints( + NonOverlapConstraintExemptions *exemptions, unsigned int priority) + : CompoundConstraint(vpsc::HORIZONTAL, priority), + pairInfoListSorted(false), + initialSortCompleted(false), + m_exemptions(exemptions) +{ + // All work is done by repeated addShape() calls. +} + +void NonOverlapConstraints::addShape(unsigned id, double halfW, double halfH, + unsigned int group, std::set<unsigned> exemptions) +{ + // Setup pairInfos for all other shapes. + for (std::map<unsigned, OverlapShapeOffsets>::iterator curr = + shapeOffsets.begin(); curr != shapeOffsets.end(); ++curr) + { + unsigned otherId = curr->first; + if ((shapeOffsets[otherId].group == group) && (id != otherId) && exemptions.count(otherId)==0) + { + if (m_exemptions && + m_exemptions->shapePairIsExempt(ShapePair(otherId, id))) + { + continue; + } + + // Apply non-overlap only to objects in the same group (cluster). + pairInfoList.push_back(ShapePairInfo(otherId, id)); + } + } + + shapeOffsets[id] = OverlapShapeOffsets(id, halfW, halfH, group); +} + +void NonOverlapConstraints::resizeShape(unsigned id, double halfW, double halfH) +{ + OverlapShapeOffsets oso = shapeOffsets[id]; + oso.resize(halfW, halfH); +} + +void NonOverlapConstraints::removeShape(unsigned id) +{ + // Remove the OverlapShapeOffsets object for this id. + shapeOffsets.erase(id); + // Remove all ShapePairInfo objects having this id as one of their two indices. + std::list<ShapePairInfo>::iterator it = pairInfoList.begin(); + while (it != pairInfoList.end()) { + ShapePairInfo spi = *it; + if (spi.varIndex1==id || spi.varIndex2==id) { + it = pairInfoList.erase(it); // now it points to next list element after one erased + } else { + it++; + } + } +} + +// This is expected to be called after all addNode calls. +void NonOverlapConstraints::addCluster(Cluster *cluster, unsigned int group) +{ + unsigned id = cluster->clusterVarId; + // Setup pairInfos for all other shapes. + for (std::map<unsigned, OverlapShapeOffsets>::iterator curr = + shapeOffsets.begin(); curr != shapeOffsets.end(); ++curr) + { + unsigned otherId = curr->first; + if (shapeOffsets[otherId].group != group) + { + // Don't apply if not in same group. + continue; + } + if (cluster->nodes.count(otherId) > 0) + { + // Don't apply non-overlap to child nodes. + continue; + } + if (m_cluster_cluster_exemptions.count(ShapePair(id, otherId)) > 0) + { + // Don't apply if exempt due to non-strict cluster hierarchy. + continue; + } + // Apply non-overlap only to objects in the same group (cluster). + pairInfoList.push_back(ShapePairInfo(otherId, id)); + } + + shapeOffsets[id] = OverlapShapeOffsets(id, cluster, group); +} + + +void NonOverlapConstraints::setClusterClusterExemptions( + std::set<ShapePair> exemptions) +{ + m_cluster_cluster_exemptions = exemptions; +} + +void NonOverlapConstraints::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + COLA_UNUSED(dim); + COLA_UNUSED(vars); +} + +void NonOverlapConstraints::computeOverlapForShapePairInfo(ShapePairInfo& info, + vpsc::Variables vs[]) +{ + OverlapShapeOffsets& shape1 = shapeOffsets[info.varIndex1]; + OverlapShapeOffsets& shape2 = shapeOffsets[info.varIndex2]; + + double xPos1 = vs[0][info.varIndex1]->finalPosition; + double xPos2 = vs[0][info.varIndex2]->finalPosition; + double yPos1 = vs[1][info.varIndex1]->finalPosition; + double yPos2 = vs[1][info.varIndex2]->finalPosition; + + double left1 = xPos1 - shape1.halfDim[0]; + double right1 = xPos1 + shape1.halfDim[0]; + double bottom1 = yPos1 - shape1.halfDim[1]; + double top1 = yPos1 + shape1.halfDim[1]; + + if (shape1.cluster) + { + COLA_ASSERT(shape1.halfDim[0] == 0); + COLA_ASSERT(shape1.halfDim[1] == 0); + COLA_ASSERT(info.varIndex1 + 1 < vs[0].size()); + right1 = vs[0][info.varIndex1 + 1]->finalPosition; + COLA_ASSERT(info.varIndex1 + 1 < vs[1].size()); + top1 = vs[1][info.varIndex1 + 1]->finalPosition; + left1 -= shape1.rectPadding.min(XDIM); + bottom1 -= shape1.rectPadding.min(YDIM); + right1 += shape1.rectPadding.max(XDIM); + top1 += shape1.rectPadding.max(YDIM); + } + + double left2 = xPos2 - shape2.halfDim[0]; + double right2 = xPos2 + shape2.halfDim[0]; + double bottom2 = yPos2 - shape2.halfDim[1]; + double top2 = yPos2 + shape2.halfDim[1]; + + if (shape2.cluster) + { + COLA_ASSERT(shape2.halfDim[0] == 0); + COLA_ASSERT(shape2.halfDim[1] == 0); + COLA_ASSERT(info.varIndex2 + 1 < vs[0].size()); + right2 = vs[0][info.varIndex2 + 1]->finalPosition; + COLA_ASSERT(info.varIndex2 + 1 < vs[1].size()); + top2 = vs[1][info.varIndex2 + 1]->finalPosition; + left2 -= shape2.rectPadding.min(XDIM); + bottom2 -= shape2.rectPadding.min(YDIM); + right2 += shape2.rectPadding.max(XDIM); + top2 += shape2.rectPadding.max(YDIM); + } + + // If lr < 0, then left edge of shape1 is on the left + // of right edge of shape2. + double spaceR = left2 - right1; + double spaceL = left1 - right2; + // Below + double spaceA = bottom2 - top1; + // Above + double spaceB = bottom1 - top2; + + double costL = 0; + double costR = 0; + double costB = 0; + double costA = 0; + info.overlapMax = 0; + bool xOverlap = false; + bool yOverlap = false; + if ((spaceR < 0) && (spaceL < 0)) + { + costL = std::max(-spaceL, 0.0); + costR = std::max(-spaceR, 0.0); + + info.overlapMax = std::max(costL, costR); + + xOverlap = true; + } + if ((spaceB < 0) && (spaceA < 0)) + { + costB = std::max(-spaceB, 0.0); + costA = std::max(-spaceA, 0.0); + + info.overlapMax = std::max(info.overlapMax, costB); + info.overlapMax = std::max(info.overlapMax, costA); + + yOverlap = true; + } + + if (!xOverlap || !yOverlap) + { + // Overlap must occur in both dimensions. + info.overlapMax = 0; + } + else + { + // Increase the overlap value for overlap where one shape is fully + // within the other. This results in these situations being + // resolved first and will sometimes prevent us from committing to + // bad non-overlap choices and getting stuck later. + // XXX Another alternative would be to look at previously added + // non-overlap constraints that become unsatified and then + // allow them to be rechosen maybe just a single time. + double penalty = 100000; + if ( (left1 >= left2) && (right1 <= right2) && + (bottom1 >= bottom2) && (top1 <= top2) ) + { + // Shape 1 is inside shape 2. + double smallShapeArea = (right1 - left1) * (top1 - bottom1); + info.overlapMax = penalty + smallShapeArea; + } + else if ( (left2 >= left1) && (right2 <= right1) && + (bottom2 >= bottom1) && (top2 <= top1) ) + { + // Shape 2 is inside shape 1. + double smallShapeArea = (right2 - left2) * (top2 - bottom2); + info.overlapMax = penalty + smallShapeArea; + } + // There is overlap. + //printf("[%02d][%02d] L %g, R %G, B %g, A %g\n", info.varIndex1, + // info.varIndex2, spaceL, spaceR, spaceB, spaceA); + } +} + +std::string NonOverlapConstraints::toString(void) const +{ + std::ostringstream stream; + stream << "NonOverlapConstraints()"; + return stream.str(); +} + +void NonOverlapConstraints::computeAndSortOverlap(vpsc::Variables vs[]) +{ + for (std::list<ShapePairInfo>::iterator curr = pairInfoList.begin(); + curr != pairInfoList.end(); ++curr) + { + ShapePairInfo& info = static_cast<ShapePairInfo&> (*curr); + + if (info.processed) + { + // Once we reach the processed nodes, which will always be at + // the back, we can some computing overlap since this no longer + // matters. + break; + } + computeOverlapForShapePairInfo(info, vs); + } + pairInfoList.sort(); +} + + +void NonOverlapConstraints::markCurrSubConstraintAsActive(const bool satisfiable) +{ + ShapePairInfo info = pairInfoList.front(); + pairInfoList.pop_front(); + + info.processed = true; + info.satisfied = satisfiable; + info.overlapMax = 0; + + pairInfoList.push_back(info); + pairInfoListSorted = false; +} + + + +SubConstraintAlternatives +NonOverlapConstraints::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + SubConstraintAlternatives alternatives; + if (initialSortCompleted == false) + { + // Initally sort the shape pair info objects. + computeAndSortOverlap(vs); + pairInfoListSorted = true; + initialSortCompleted = true; + } + + // Take the first in the list. + ShapePairInfo& info = pairInfoList.front(); + if (pairInfoListSorted == false) + { + // Only need to compute if not sorted. + computeOverlapForShapePairInfo(info, vs); + } + + if (info.overlapMax == 0) + { + if (pairInfoListSorted) + { + // Seeing no overlap in the sorted list means we have solved + // all non-overlap. Nothing more to do. + _currSubConstraintIndex = pairInfoList.size(); + return alternatives; + } + computeAndSortOverlap(vs); + pairInfoListSorted = true; + return alternatives; + } + OverlapShapeOffsets& shape1 = shapeOffsets[info.varIndex1]; + OverlapShapeOffsets& shape2 = shapeOffsets[info.varIndex2]; + + double xSepL = shape1.halfDim[0] + shape2.halfDim[0]; + double ySepB = shape1.halfDim[1] + shape2.halfDim[1]; + double xSepR = xSepL; + double ySepT = ySepB; + + unsigned varIndexL1 = info.varIndex1; + unsigned varIndexL2 = info.varIndex2; + // Clusters have left and right variables, instead of centre variables. + unsigned varIndexR1 = + (shape1.cluster) ? (info.varIndex1 + 1) : info.varIndex1; + unsigned varIndexR2 = + (shape2.cluster) ? (info.varIndex2 + 1) : info.varIndex2; + + assertValidVariableIndex(vs[XDIM], varIndexL1); + assertValidVariableIndex(vs[YDIM], varIndexL1); + assertValidVariableIndex(vs[XDIM], varIndexR1); + assertValidVariableIndex(vs[YDIM], varIndexR1); + assertValidVariableIndex(vs[XDIM], varIndexL2); + assertValidVariableIndex(vs[YDIM], varIndexL2); + assertValidVariableIndex(vs[XDIM], varIndexR2); + assertValidVariableIndex(vs[YDIM], varIndexR2); + + // + double xSepCostL = xSepL; + double xSepCostR = xSepR; + double ySepCostB = ySepB; + double ySepCostT = ySepT; + + double desiredX1 = vs[XDIM][info.varIndex1]->desiredPosition; + double desiredY1 = vs[YDIM][info.varIndex1]->desiredPosition; + double desiredX2 = vs[XDIM][info.varIndex2]->desiredPosition; + double desiredY2 = vs[YDIM][info.varIndex2]->desiredPosition; + + // Clusters have two variables instead of a centre variable -- one for + // each boundary side, so we need to remap the desired positions and the + // separations values for the purposes of cost sorting. + if (shape1.cluster) + { + double width = vs[XDIM][info.varIndex1 + 1]->finalPosition - + vs[XDIM][info.varIndex1]->finalPosition; + double height = vs[YDIM][info.varIndex1 + 1]->finalPosition - + vs[YDIM][info.varIndex1]->finalPosition; + desiredX1 += width / 2; + desiredY1 += height / 2; + xSepCostL += width / 2; + xSepCostR += width / 2; + ySepCostB += height / 2; + ySepCostT += height / 2; + xSepL += shape1.rectPadding.min(XDIM); + xSepR += shape1.rectPadding.max(XDIM); + ySepB += shape1.rectPadding.min(YDIM); + ySepT += shape1.rectPadding.max(YDIM); + } + if (shape2.cluster) + { + double width = vs[XDIM][info.varIndex2 + 1]->finalPosition - + vs[XDIM][info.varIndex2]->finalPosition; + double height = vs[YDIM][info.varIndex2 + 1]->finalPosition - + vs[YDIM][info.varIndex2]->finalPosition; + desiredX2 += width / 2; + desiredY2 += height / 2; + xSepCostL += width / 2; + xSepCostR += width / 2; + ySepCostB += height / 2; + ySepCostT += height / 2; + xSepL += shape2.rectPadding.min(XDIM); + xSepR += shape2.rectPadding.max(XDIM); + ySepB += shape2.rectPadding.min(YDIM); + ySepT += shape2.rectPadding.max(YDIM); + } + + // We get problems with numerical inaccuracy in the topology constraint + // generation, so make sure the rectagles are separated by at least a + // tiny distance. + xSepL += 10e-10; + xSepR += 10e-10; + ySepB += 10e-10; + ySepT += 10e-10; + + // Compute the cost to move in each direction based on the + // desired positions for the two objects. + double costR = xSepCostR - (desiredX2 - desiredX1); + double costL = xSepCostL - (desiredX1 - desiredX2); + + double costT = ySepCostT - (desiredY2 - desiredY1); + double costB = ySepCostB - (desiredY1 - desiredY2); + + vpsc::Constraint constraintL(vs[XDIM][varIndexR2], + vs[XDIM][varIndexL1], xSepL); + alternatives.push_back(SubConstraint(XDIM, constraintL, costL)); + + vpsc::Constraint constraintR(vs[XDIM][varIndexR1], + vs[XDIM][varIndexL2], xSepR); + alternatives.push_back(SubConstraint(XDIM, constraintR, costR)); + + vpsc::Constraint constraintB(vs[YDIM][varIndexR2], + vs[YDIM][varIndexL1], ySepB); + alternatives.push_back(SubConstraint(YDIM, constraintB, costB)); + + vpsc::Constraint constraintT(vs[YDIM][varIndexR1], + vs[YDIM][varIndexL2], ySepT); + alternatives.push_back(SubConstraint(YDIM, constraintT, costT)); + + //fprintf(stderr, "===== NONOVERLAP ALTERNATIVES -====== \n"); + + return alternatives; +} + + +bool NonOverlapConstraints::subConstraintsRemaining(void) const +{ + //printf(". %3d of %4d\n", _currSubConstraintIndex, pairInfoList.size()); + return _currSubConstraintIndex < pairInfoList.size(); +} + + +void NonOverlapConstraints::markAllSubConstraintsAsInactive(void) +{ + for (std::list<ShapePairInfo>::iterator curr = pairInfoList.begin(); + curr != pairInfoList.end(); ++curr) + { + ShapePairInfo& info = (*curr); + info.satisfied = false; + info.processed = false; + } + _currSubConstraintIndex = 0; + initialSortCompleted = false; +} + + +void NonOverlapConstraints::generateSeparationConstraints( + const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs, + std::vector<vpsc::Rectangle*>& boundingBoxes) +{ + for (std::list<ShapePairInfo>::iterator info = pairInfoList.begin(); + info != pairInfoList.end(); ++info) + { + assertValidVariableIndex(vs, info->varIndex1); + assertValidVariableIndex(vs, info->varIndex2); + + OverlapShapeOffsets& shape1 = shapeOffsets[info->varIndex1]; + OverlapShapeOffsets& shape2 = shapeOffsets[info->varIndex2]; + + vpsc::Rectangle rect1 = (shape1.cluster) ? + shape1.cluster->bounds : *boundingBoxes[info->varIndex1]; + vpsc::Rectangle rect2 = (shape2.cluster) ? + shape2.cluster->bounds : *boundingBoxes[info->varIndex2]; + + double pos1 = rect1.getCentreD(dim); + double pos2 = rect2.getCentreD(dim); + + double below1 = shape1.halfDim[dim]; + double above1 = shape1.halfDim[dim]; + double below2 = shape2.halfDim[dim]; + double above2 = shape2.halfDim[dim]; + + vpsc::Variable *varLeft1 = nullptr; + vpsc::Variable *varLeft2 = nullptr; + vpsc::Variable *varRight1 = nullptr; + vpsc::Variable *varRight2 = nullptr; + if (shape1.cluster) + { + // Must constraint to cluster boundary variables. + varLeft1 = vs[shape1.cluster->clusterVarId]; + varRight1 = vs[shape1.cluster->clusterVarId + 1]; + rect1 = shape1.cluster->margin().rectangleByApplyingBox(rect1); + below1 = shape1.cluster->margin().min(dim); + above1 = shape1.cluster->margin().max(dim); + } + else + { + // Must constrain to rectangle centre postion variable. + varLeft1 = varRight1 = vs[info->varIndex1]; + } + + if (shape2.cluster) + { + // Must constraint to cluster boundary variables. + varLeft2 = vs[shape2.cluster->clusterVarId]; + varRight2 = vs[shape2.cluster->clusterVarId + 1]; + rect2 = shape2.cluster->margin().rectangleByApplyingBox(rect2); + below2 = shape2.cluster->margin().min(dim); + above2 = shape2.cluster->margin().max(dim); + } + else + { + // Must constrain to rectangle centre postion variable. + varLeft2 = varRight2 = vs[info->varIndex2]; + } + + if (rect1.overlapD(!dim, &rect2) > 0.0005) + { + vpsc::Constraint *constraint = nullptr; + if (pos1 < pos2) + { + constraint = new vpsc::Constraint(varRight1, varLeft2, + above1 + below2); + } + else + { + constraint = new vpsc::Constraint(varRight2, varLeft1, + below1 + above2); + } + constraint->creator = this; + cs.push_back(constraint); + } + } +} + + +} // namespace cola diff --git a/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.h b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.h new file mode 100644 index 0000000..0904ece --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.h @@ -0,0 +1,210 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2010-2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#ifndef COLA_CC_NONOVERLAPCONSTRAINTS_H +#define COLA_CC_NONOVERLAPCONSTRAINTS_H + +#include <vector> + +#include "libcola/cola.h" +#include "libcola/compound_constraints.h" +#include "libcola/shapepair.h" + +namespace vpsc { +class Rectangle; +} + +namespace cola { + +class Cluster; + +class OverlapShapeOffsets : public SubConstraintInfo +{ + public: + OverlapShapeOffsets(unsigned ind, double xOffset, double yOffset, + unsigned int group) + : SubConstraintInfo(ind), + cluster(nullptr), + rectPadding(0), + group(group) + { + halfDim[0] = xOffset; + halfDim[1] = yOffset; + } + OverlapShapeOffsets(unsigned ind, Cluster *cluster, unsigned int group) + : SubConstraintInfo(ind), + cluster(cluster), + rectPadding(cluster->margin()), + group(group) + { + halfDim[0] = 0; + halfDim[1] = 0; + } + OverlapShapeOffsets() + : SubConstraintInfo(1000000), + cluster(nullptr), + rectPadding(0) + { + } + bool usesClusterBounds(void) const + { + return (cluster && !cluster->clusterIsFromFixedRectangle()); + } + void resize(double xOffset, double yOffset) + { + halfDim[0] = xOffset; + halfDim[1] = yOffset; + } + Cluster *cluster; + double halfDim[2]; // Half width and height values. + Box rectPadding; // Used for cluster padding. + unsigned int group; +}; + + +class ShapePairInfo +{ + public: + ShapePairInfo(unsigned ind1, unsigned ind2, unsigned ord = 1) + : order(ord), + satisfied(false), + processed(false) + { + COLA_ASSERT(ind1 != ind2); + // Assign the lesser value to varIndex1. + varIndex1 = (ind1 < ind2) ? ind1 : ind2; + // Assign the greater value to varIndex2. + varIndex2 = (ind1 > ind2) ? ind1 : ind2; + } + bool operator<(const ShapePairInfo& rhs) const + { + // Make sure the processed ones are at the end after sorting. + int processedInt = processed ? 1 : 0; + int rhsProcessedInt = rhs.processed ? 1 : 0; + if (processedInt != rhsProcessedInt) + { + return processedInt < rhsProcessedInt; + } + // Use cluster ordering for primary sorting. + if (order != rhs.order) + { + return order < rhs.order; + } + return overlapMax > rhs.overlapMax; + } + unsigned short order; + unsigned short varIndex1; + unsigned short varIndex2; + bool satisfied; + bool processed; + double overlapMax; +}; + + +// Stores IDs of all rectangles exempt from non-overlap constraints. +class NonOverlapConstraintExemptions { + public: + NonOverlapConstraintExemptions(); + void addExemptGroupOfNodes(ListOfNodeIndexes listOfNodeGroups); + bool shapePairIsExempt(ShapePair shapePair) const; + std::set<ShapePair> getExemptPairs(void) {return m_exempt_pairs;} + + private: + std::set<ShapePair> m_exempt_pairs; +}; + +// Non-overlap constraints prevent a set of given shapes from overlapping. +class NonOverlapConstraints : public CompoundConstraint { + public: + NonOverlapConstraints(NonOverlapConstraintExemptions *exemptions, + unsigned int priority = PRIORITY_NONOVERLAP); + //! @brief Use this method to add all the shapes between which you want + //! to prevent overlaps. + //! @param id This will be used as index into both the vars and + //! boundingBoxes vectors when you call the + //! generateSeparationConstraints method. + //! @param halfW If you add two shapes with half-widths hwi and hwj, then + //! if a horizontal separation constraint is generated between + //! them its gap will be hwi + hwj. + //! @param halfH Similar to halfW. + //! @param group Assign a group number to this shape. A separation constraint + //! will be generated between two shapes only if they belong to + //! the same group. This is useful for clusters. + //! @param exemptions Optional set of IDs of shapes to be skipped, i.e. such that + //! a separation constraint should /not/ be generated between + //! that shape and the one being added. + void addShape(unsigned id, double halfW, double halfH, + unsigned int group = 1, std::set<unsigned> exemptions = std::set<unsigned>()); + void resizeShape(unsigned id, double halfW, double halfH); + void removeShape(unsigned id); + void addCluster(Cluster *cluster, unsigned int group); + void computeAndSortOverlap(vpsc::Variables vs[]); + void markCurrSubConstraintAsActive(const bool satisfiable); + void markAllSubConstraintsAsInactive(void); + bool subConstraintsRemaining(void) const; + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + std::string toString(void) const; + void setClusterClusterExemptions(std::set<ShapePair> exemptions); + + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& gcs); + //! @brief Generate separation constraints in one dimension, to ensure + //! nonoverlap between all shapes in that dimension. + //! @param dim The dimension for which to generate constraints. + //! @param vars The variables between which the constraints will hold. + //! @param gcs The generated constraints will be added to this vector. + //! @param boundingBoxes For those id's corresponding to added shapes + //! (not clusters), the rectangle boundingBox[id] will be consulted + //! in order to determine: + //! (1) whether a separation constraint is called for, i.e. whether the + //! shapes in question span any of the same coods in the dimension + //! opposite to dim; + //! (2) which var is left and which is right in the separation constraint. + //! Note however that the dimensions of the boundingBoxes do NOT determine + //! the gaps of the separation constraints, which are instead based on the + //! half-width and half-height passed when adding the shapes. + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& gcs, + std::vector<vpsc::Rectangle*>& boundingBoxes); + + private: + void computeOverlapForShapePairInfo(ShapePairInfo& info, + vpsc::Variables vs[]); + + std::list<ShapePairInfo> pairInfoList; + std::map<unsigned, OverlapShapeOffsets> shapeOffsets; + bool pairInfoListSorted; + bool initialSortCompleted; + + // Cluster variables + size_t clusterVarStartIndex; + size_t currClusterIndex; + size_t clusterMode; + + NonOverlapConstraintExemptions *m_exemptions; + std::set<ShapePair> m_cluster_cluster_exemptions; +}; + +} // namespace cola +#endif // COLA_CC_NONOVERLAPCONSTRAINTS diff --git a/src/3rdparty/adaptagrams/libcola/cluster.cpp b/src/3rdparty/adaptagrams/libcola/cluster.cpp new file mode 100644 index 0000000..6fbfc0b --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cluster.cpp @@ -0,0 +1,719 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer + * Michael Wybrow +*/ + +#include "libvpsc/assertions.h" +#include "libcola/commondefs.h" +#include "libcola/cola.h" +#include "libcola/convex_hull.h" +#include "libcola/cluster.h" + +using vpsc::generateXConstraints; +using vpsc::generateYConstraints; +using namespace std; + +namespace cola { + +Cluster::Cluster() + : bounds(), + clusterVarId(0), + varWeight(0.0001), + internalEdgeWeightFactor(1.), + desiredBoundsSet(false), + desiredBounds() +{ + // XXX We use a really low weight here until we properly set the source + // of the variable value back in updatePositions() type manner. + varWeight = 0.0000001; +} + +Cluster::~Cluster() +{ + for_each(clusters.begin(), clusters.end(), delete_object()); + clusters.clear(); +} + +void Cluster::setDesiredBounds(const vpsc::Rectangle db) +{ + desiredBoundsSet = true; + desiredBounds = db; +} + +void Cluster::unsetDesiredBounds(void) +{ + desiredBoundsSet=false; +} + + +// Checks to see if the shape at the given index is contained within this +// cluster or its child clusters. +// +void Cluster::countContainedNodes(std::vector<unsigned>& counts) +{ + vector<unsigned> invalidNodes; + for (set<unsigned>::iterator it = nodes.begin(); it != nodes.end(); ++it) + { + unsigned nodeIndex = *it; + if (nodeIndex < counts.size()) + { + // Node index is valid, increase count. + counts[*it] += 1; + } + else + { + fprintf(stderr, "Warning: Invalid node index %u specified in " + "cluster. Ignoring...\n", nodeIndex); + invalidNodes.push_back(nodeIndex); + } + } + for (size_t i = 0; i < invalidNodes.size(); ++i) + { + nodes.erase(invalidNodes[i]); + } + + for (vector<Cluster*>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->countContainedNodes(counts); + } +} + +void Cluster::computeBoundingRect(const vpsc::Rectangles& rs) +{ + bounds = vpsc::Rectangle(); + for (vector<Cluster*>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->computeBoundingRect(rs); + vpsc::Rectangle rectangle = + (*i)->margin().rectangleByApplyingBox((*i)->bounds); + bounds = bounds.unionWith(rectangle); + } + for (set<unsigned>::const_iterator i = nodes.begin(); + i != nodes.end(); ++i) + { + vpsc::Rectangle* r=rs[*i]; + bounds = bounds.unionWith(*r); + } + bounds = padding().rectangleByApplyingBox(bounds); +} + +void Cluster::computeVarRect(vpsc::Variables& vars, size_t dim) +{ + if ((clusterVarId > 0) && (vars.size() > clusterVarId)) + { + varRect.setMinD(dim, vars[clusterVarId]->finalPosition); + varRect.setMaxD(dim, vars[clusterVarId + 1]->finalPosition); + } + + for (vector<Cluster*>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->computeVarRect(vars, dim); + } +} + +bool Cluster::clusterIsFromFixedRectangle(void) const +{ + return false; +} + +void ConvexCluster::computeBoundary(const vpsc::Rectangles& rs) +{ + unsigned n = 4 * nodes.size(); + valarray<double> X(n); + valarray<double> Y(n); + unsigned pctr = 0; + vector<unsigned> nodesVector(nodes.begin(), nodes.end()); + for (size_t i = 0; i < nodesVector.size(); ++i) + { + vpsc::Rectangle* r=rs[nodesVector[i]]; + // Bottom Right + X[pctr]=r->getMaxX(); + Y[pctr++]=r->getMinY(); + // Top Right + X[pctr]=r->getMaxX(); + Y[pctr++]=r->getMaxY(); + // Top Left + X[pctr]=r->getMinX(); + Y[pctr++]=r->getMaxY(); + // Bottom Left + X[pctr]=r->getMinX(); + Y[pctr++]=r->getMinY(); + } + /* + for(unsigned i=0;i<n;i++) { + printf("X[%d]=%f, Y[%d]=%f;\n",i,X[i],i,Y[i]); + } + */ + vector<unsigned> hull; + hull::convex(X,Y,hull); + hullX.resize(hull.size()); + hullY.resize(hull.size()); + hullRIDs.resize(hull.size()); + hullCorners.resize(hull.size()); + for (unsigned j=0;j<hull.size();j++) + { + hullX[j]=X[hull[j]]; + hullY[j]=Y[hull[j]]; + hullRIDs[j]=nodesVector[hull[j]/4]; + hullCorners[j]=hull[j]%4; + } +} + + +void ConvexCluster::printCreationCode(FILE *fp) const +{ + fprintf(fp, " ConvexCluster *cluster%llu = new ConvexCluster();\n", + (unsigned long long) this); + for(set<unsigned>::const_iterator i = nodes.begin(); + i != nodes.end(); ++i) + { + fprintf(fp, " cluster%llu->addChildNode(%u);\n", + (unsigned long long) this, *i); + } + for(vector<Cluster *>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->printCreationCode(fp); + fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n", + (unsigned long long) this, (unsigned long long) *i); + } +} + +void ConvexCluster::outputToSVG(FILE *fp) const +{ + for(vector<Cluster *>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->outputToSVG(fp); + } +} + + +RectangularCluster::RectangularCluster() + : Cluster(), + m_rectangle_index(-1), + m_margin(0), + m_padding(0) +{ + minEdgeRect[vpsc::XDIM] = nullptr; + minEdgeRect[vpsc::YDIM] = nullptr; + maxEdgeRect[vpsc::XDIM] = nullptr; + maxEdgeRect[vpsc::YDIM] = nullptr; +} + +RectangularCluster::RectangularCluster(unsigned rectIndex) + : Cluster(), + m_rectangle_index(rectIndex), + m_margin(0), + m_padding(0) +{ + minEdgeRect[vpsc::XDIM] = nullptr; + minEdgeRect[vpsc::YDIM] = nullptr; + maxEdgeRect[vpsc::XDIM] = nullptr; + maxEdgeRect[vpsc::YDIM] = nullptr; +} + +RectangularCluster::~RectangularCluster() +{ + for (size_t dim = 0; dim < 2; ++dim) + { + if (minEdgeRect[dim]) + { + delete minEdgeRect[dim]; + minEdgeRect[dim] = nullptr; + } + if (maxEdgeRect[dim]) + { + delete maxEdgeRect[dim]; + maxEdgeRect[dim] = nullptr; + } + } +} + +void RectangularCluster::setMargin(const Box margin) +{ + m_margin = margin; +} + + +void RectangularCluster::setMargin(double margin) +{ + m_margin = Box(margin); +} + + +Box RectangularCluster::margin(void) const +{ + return m_margin; +} + + +void RectangularCluster::setPadding(const Box padding) +{ + m_padding = padding; +} + + +void RectangularCluster::setPadding(double padding) +{ + m_padding = Box(padding); +} + + +Box RectangularCluster::padding(void) const +{ + return m_padding; +} + + +void RectangularCluster::countContainedNodes(std::vector<unsigned>& counts) +{ + if (m_rectangle_index >= 0) + { + // This cluster is the shape in question. + counts[m_rectangle_index] += 1; + } + Cluster::countContainedNodes(counts); +} + + +void RectangularCluster::generateFixedRectangleConstraints( + cola::CompoundConstraints& idleConstraints, + vpsc::Rectangles& rc, vpsc::Variables (&vars)[2]) const +{ + COLA_UNUSED(vars); + + if (m_rectangle_index < 0) + { + // Not based on a Rectangle. + return; + } + + double halfWidth = rc[m_rectangle_index]->width() / 2; + double halfHeight = rc[m_rectangle_index]->height() / 2; + + cola::SeparationConstraint *sc = + new cola::SeparationConstraint(vpsc::XDIM, clusterVarId, + m_rectangle_index, halfWidth, true); + idleConstraints.push_back(sc); + sc = new cola::SeparationConstraint(vpsc::XDIM, + m_rectangle_index, clusterVarId + 1, halfWidth, true); + idleConstraints.push_back(sc); + + sc = new cola::SeparationConstraint(vpsc::YDIM, + clusterVarId, m_rectangle_index, halfHeight, true); + idleConstraints.push_back(sc); + sc = new cola::SeparationConstraint(vpsc::YDIM, + m_rectangle_index, clusterVarId + 1, halfHeight, true); + idleConstraints.push_back(sc); +} + + +void RectangularCluster::computeBoundary(const vpsc::Rectangles& rs) +{ + double xMin=DBL_MAX, xMax=-DBL_MAX, yMin=DBL_MAX, yMax=-DBL_MAX; + for (std::set<unsigned>::iterator it = nodes.begin(); + it != nodes.end(); ++it) + { + xMin=std::min(xMin,rs[*it]->getMinX()); + xMax=std::max(xMax,rs[*it]->getMaxX()); + yMin=std::min(yMin,rs[*it]->getMinY()); + yMax=std::max(yMax,rs[*it]->getMaxY()); + } + hullX.resize(4); + hullY.resize(4); + hullX[3]=xMin; + hullY[3]=yMin; + hullX[2]=xMin; + hullY[2]=yMax; + hullX[1]=xMax; + hullY[1]=yMax; + hullX[0]=xMax; + hullY[0]=yMin; +} + + +void RectangularCluster::printCreationCode(FILE *fp) const +{ + fprintf(fp, " RectangularCluster *cluster%llu = " + "new RectangularCluster(", + (unsigned long long) this); + if (m_rectangle_index != -1) + { + fprintf(fp, "%d", m_rectangle_index); + } + fprintf(fp, ");\n"); + if (!m_margin.empty()) + { + fprintf(fp, " cluster%llu->setMargin(", + (unsigned long long) this); + m_margin.outputCode(fp); + fprintf(fp, ");\n"); + } + if (!m_padding.empty()) + { + fprintf(fp, " cluster%llu->setPadding(", + (unsigned long long) this); + m_padding.outputCode(fp); + fprintf(fp, ");\n"); + } + for(set<unsigned>::const_iterator i = nodes.begin(); + i != nodes.end(); ++i) + { + fprintf(fp, " cluster%llu->addChildNode(%u);\n", + (unsigned long long) this, *i); + } + for(vector<Cluster *>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->printCreationCode(fp); + fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n", + (unsigned long long) this, (unsigned long long) *i); + } +} + +void RectangularCluster::outputToSVG(FILE *fp) const +{ + double rounding = 4; + if (varRect.isValid()) + { + fprintf(fp, "<rect id=\"cluster-%llu-r\" x=\"%g\" y=\"%g\" width=\"%g\" " + "height=\"%g\" style=\"stroke-width: 1px; stroke: black; " + "fill: green; fill-opacity: 0.3;\" rx=\"%g\" ry=\"%g\" />\n", + (unsigned long long) this, varRect.getMinX(), varRect.getMinY(), + varRect.getMaxX() - varRect.getMinX(), + varRect.getMaxY() - varRect.getMinY(), rounding, rounding); + } + else + { + fprintf(fp, "<rect id=\"cluster-%llu\" x=\"%g\" y=\"%g\" width=\"%g\" " + "height=\"%g\" style=\"stroke-width: 1px; stroke: black; " + "fill: red; fill-opacity: 0.3;\" rx=\"%g\" ry=\"%g\" />\n", + (unsigned long long) this, bounds.getMinX(), bounds.getMinY(), + bounds.getMaxX() - bounds.getMinX(), + bounds.getMaxY() - bounds.getMinY(), rounding, rounding); + } + + for(vector<Cluster *>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->outputToSVG(fp); + } +} + + + +int RectangularCluster::rectangleIndex(void) const +{ + return m_rectangle_index; +} + +bool RectangularCluster::clusterIsFromFixedRectangle(void) const +{ + return (m_rectangle_index >= 0); +} + +void RectangularCluster::computeBoundingRect(const vpsc::Rectangles& rs) +{ + if (clusterIsFromFixedRectangle()) + { + // For bounds, just use this shape's rectangle. + bounds = *(rs[m_rectangle_index]); + } + else + { + Cluster::computeBoundingRect(rs); + } +} +void RectangularCluster::addChildNode(unsigned index) +{ + if ((m_rectangle_index == (int) index) && (m_rectangle_index > 0)) + { + fprintf(stderr, "Warning: ignoring cluster (%u) added as child of " + "itself.\n", index); + return; + } + Cluster::addChildNode(index); +} + + +RootCluster::RootCluster() + : m_allows_multiple_parents(false) +{ +} + +void Cluster::recPathToCluster(RootCluster *rootCluster, Clusters currentPath) +{ + // Reset cluster-cluster overlap exceptions. + m_cluster_cluster_overlap_exceptions.clear(); + m_nodes_replaced_with_clusters.clear(); + m_overlap_replacement_map.clear(); + + // Add this cluster to the path. + currentPath.push_back(this); + + // Recusively all on each child cluster. + for (unsigned i = 0; i < clusters.size(); ++i) + { + clusters[i]->recPathToCluster(rootCluster, currentPath); + } + + // And store the path to each child node. + for (std::set<unsigned>::iterator it = nodes.begin(); + it != nodes.end(); ++it) + { + rootCluster->m_cluster_vectors_leading_to_nodes[*it]. + push_back(currentPath); + } +} + + +void RootCluster::calculateClusterPathsToEachNode(size_t nodesCount) +{ + m_cluster_vectors_leading_to_nodes.clear(); + m_cluster_vectors_leading_to_nodes.resize(nodesCount); + + recPathToCluster(this, Clusters()); + + for (unsigned i = 0; i < m_cluster_vectors_leading_to_nodes.size(); ++i) + { + size_t paths = m_cluster_vectors_leading_to_nodes[i].size(); + for (size_t j = 1; j < paths; ++j) + { + for (size_t k = 0; k < j; ++k) + { + // For each pair of paths. + + // Find the lowest common ancestor by finding where the two + // paths from the root cluster to node i diverge. + Clusters pathJ = m_cluster_vectors_leading_to_nodes[i][j]; + Clusters pathK = m_cluster_vectors_leading_to_nodes[i][k]; + size_t lcaIndex = 0; + while ((lcaIndex < pathJ.size()) && + (lcaIndex < pathK.size()) && + (pathJ[lcaIndex] == pathK[lcaIndex])) + { + ++lcaIndex; + } + COLA_ASSERT(lcaIndex > 0); + + // lcaIndex will be the clusters/nodes that need to overlap + // due to these two paths to node i. + size_t lcaChildJIndex = i; + size_t lcaChildKIndex = i; + Cluster *lcaChildJCluster = nullptr; + Cluster *lcaChildKCluster = nullptr; + + // lcaIndex < path{J,K}.size() means the child J or K of + // the lca is a Cluster. At least one of them will always + // be a cluster. + COLA_ASSERT((lcaIndex < pathJ.size()) || + (lcaIndex < pathK.size())); + if (lcaIndex < pathJ.size()) + { + lcaChildJCluster = pathJ[lcaIndex]; + lcaChildJIndex = lcaChildJCluster->clusterVarId; + } + if (lcaIndex < pathK.size()) + { + lcaChildKCluster = pathK[lcaIndex]; + lcaChildKIndex = lcaChildKCluster->clusterVarId; + } + + // We want to exclude the overlapping children of the lca + // from having non-overlap constraints generated for them + // (siblings of a particular cluster usually have + // non-overlap constraints generated for them). + Cluster *lcaCluster = pathJ[lcaIndex - 1]; + lcaCluster->m_cluster_cluster_overlap_exceptions.insert( + ShapePair(lcaChildJIndex, lcaChildKIndex)); + + if (lcaChildJCluster) + { + // In cluster J, replace node i with cluster K for the + // purpose of non-overlap with siblings, and remember + // this replacement so we can still generate non-overlap + // constraints between multiple nodes that are children + // of the same overlapping clusters. + lcaChildJCluster->m_overlap_replacement_map[i] = + lcaChildKCluster; + lcaChildJCluster->m_nodes_replaced_with_clusters.insert(i); + } + + if (lcaChildKCluster) + { + // In cluster K, replace node i with cluster J for the + // purpose of non-overlap with siblings, and remember + // this replacement so we can still generate non-overlap + // constraints between multiple nodes that are children + // of the same overlapping clusters. + lcaChildKCluster->m_overlap_replacement_map[i] = + lcaChildJCluster; + lcaChildKCluster->m_nodes_replaced_with_clusters.insert(i); + } + } + } + } +} + + +void RootCluster::computeBoundary(const vpsc::Rectangles& rs) +{ + for (unsigned i = 0; i < clusters.size(); ++i) + { + clusters[i]->computeBoundary(rs); + } +} + +void RootCluster::printCreationCode(FILE *fp) const +{ + fprintf(fp, " RootCluster *cluster%llu = new RootCluster();\n", + (unsigned long long) this); + for(set<unsigned>::const_iterator i = nodes.begin(); + i != nodes.end(); ++i) + { + fprintf(fp, " cluster%llu->addChildNode(%u);\n", + (unsigned long long) this, *i); + } + for(vector<Cluster *>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->printCreationCode(fp); + fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n", + (unsigned long long) this, (unsigned long long) *i); + } +} + +void RootCluster::outputToSVG(FILE *fp) const +{ + for(vector<Cluster *>::const_iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->outputToSVG(fp); + } + +} + + +bool RootCluster::allowsMultipleParents(void) const +{ + return m_allows_multiple_parents; +} + +void RootCluster::setAllowsMultipleParents(const bool value) +{ + m_allows_multiple_parents = value; +} + +void Cluster::updateBounds(const vpsc::Dim dim) +{ + if (dim == vpsc::HORIZONTAL) + { + bounds = vpsc::Rectangle(vMin->finalPosition, vMax->finalPosition, + bounds.getMinY(), bounds.getMaxY()); + } + else + { + bounds = vpsc::Rectangle(bounds.getMinX(), bounds.getMaxX(), + vMin->finalPosition, vMax->finalPosition); + } + for (unsigned i=0; i < clusters.size(); ++i) + { + clusters[i]->updateBounds(dim); + } +} + + +void Cluster::createVars(const vpsc::Dim dim, const vpsc::Rectangles& rs, + vpsc::Variables& vars) +{ + for (vector<Cluster*>::iterator i = clusters.begin(); + i != clusters.end(); ++i) + { + (*i)->createVars(dim, rs, vars); + } + if (dim==vpsc::HORIZONTAL) + { + double desiredMinX = bounds.getMinX(), desiredMaxX = bounds.getMaxX(); + if (desiredBoundsSet) + { + desiredMinX = desiredBounds.getMinX(); + desiredMaxX = desiredBounds.getMaxX(); + } + clusterVarId = vars.size(); + vars.push_back(vXMin = new vpsc::Variable( + vars.size(), desiredMinX, varWeight)); + vars.push_back(vXMax = new vpsc::Variable( + vars.size(), desiredMaxX, varWeight)); + } + else + { + double desiredMinY = bounds.getMinY(), desiredMaxY = bounds.getMaxY(); + if (desiredBoundsSet) + { + desiredMinY = desiredBounds.getMinY(); + desiredMaxY = desiredBounds.getMaxY(); + } + clusterVarId = vars.size(); + vars.push_back(vYMin = new vpsc::Variable( + vars.size(), desiredMinY, varWeight)); + vars.push_back(vYMax = new vpsc::Variable( + vars.size(), desiredMaxY, varWeight)); + } +} + +// Returns the total area covered by contents of this cluster (not +// including space between nodes/clusters). +// +double Cluster::area(const vpsc::Rectangles& rs) +{ + double a = 0; + for (set<unsigned>::iterator i = nodes.begin(); i != nodes.end(); ++i) + { + vpsc::Rectangle *r = rs[*i]; + a += r->width() * r->height(); + } + for (Clusters::iterator i = clusters.begin(); i!= clusters.end(); ++i) + { + a += (*i)->area(rs); + } + return a; +} + +void Cluster::addChildNode(unsigned index) +{ + this->nodes.insert(index); +} + +void Cluster::addChildCluster(Cluster *cluster) +{ + if (cluster == this) + { + fprintf(stderr, "Warning: ignoring cluster added as child of itself.\n"); + return; + } + this->clusters.push_back(cluster); +} + + +} // namespace cola diff --git a/src/3rdparty/adaptagrams/libcola/cluster.h b/src/3rdparty/adaptagrams/libcola/cluster.h new file mode 100644 index 0000000..118d703 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cluster.h @@ -0,0 +1,371 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer + * Michael Wybrow +*/ + +#ifndef COLA_CLUSTER_H +#define COLA_CLUSTER_H + +#include <cstdio> + +#include "libvpsc/rectangle.h" +#include "libvpsc/variable.h" + +#include "libcola/compound_constraints.h" +#include "libcola/commondefs.h" +#include "libcola/box.h" +#include "libcola/shapepair.h" + +namespace cola { + +class Cluster; +typedef std::vector<Cluster *> Clusters; +typedef std::vector<Clusters> ClustersList; + +/** + * @brief A cluster defines a hierarchical partitioning over the nodes + * which should be kept disjoint by the layout somehow. + * + * You should not use this directly. This is an abstract base class. + * At the top level you should be using RootCluster, and then below that + * either RectangualarCLuster or ConvexCluster. + */ +class Cluster +{ + public: + Cluster(); + +// To prevent C++ objects from being destroyed in garbage collected languages +// when the libraries are called from SWIG, we hide the declarations of the +// destructors and prevent generation of default destructors. +#ifndef SWIG + virtual ~Cluster(); +#endif + virtual void computeBoundary(const vpsc::Rectangles& rs) = 0; + virtual void computeBoundingRect(const vpsc::Rectangles& rs); + + /** + * @brief Mark a rectangle as being a child of this cluster. + * + * @param[in] index The index of the Rectangle in the rectangles vector. + */ + virtual void addChildNode(unsigned index); + /** + * @brief Mark a cluster as being a sub-cluster of this cluster. + * + * @param[in] cluster The Cluster to be marked as a sub-cluster. + */ + void addChildCluster(Cluster *cluster); + + virtual cola::Box padding(void) const + { + return cola::Box(); + } + virtual cola::Box margin(void) const + { + return cola::Box(); + } + + void setDesiredBounds(const vpsc::Rectangle bounds); + void unsetDesiredBounds(); + void createVars(const vpsc::Dim dim, const vpsc::Rectangles& rs, + vpsc::Variables& vars); + virtual void printCreationCode(FILE *fp) const = 0; + virtual void countContainedNodes(std::vector<unsigned>& counts); + virtual bool clusterIsFromFixedRectangle(void) const; + virtual void outputToSVG(FILE *fp) const = 0; + + // Returns the total area covered by contents of this cluster + // (not including space between nodes/clusters). + double area(const vpsc::Rectangles& rs); + + // Sets bounds based on the finalPositions of vMin and vMax. + // + void updateBounds(const vpsc::Dim dim); + + virtual void computeVarRect(vpsc::Variables& vs, size_t dim); + + vpsc::Rectangle bounds; + vpsc::Rectangle varRect; + vpsc::Variable *vXMin, *vXMax, *vYMin, *vYMax; + + // This will be the id of the left/bottom boundary, + // and the right/top will be clusterVarId + 1. + unsigned clusterVarId; + + double varWeight; + double internalEdgeWeightFactor; + std::set<unsigned> nodes; + std::vector<Cluster*> clusters; + std::valarray<double> hullX, hullY; + + protected: + void recPathToCluster(RootCluster *rootCluster, + Clusters currentPath); + bool includesAllNodesFrom(const Cluster *rhs) const; + + // The following are for handling the generation of the correct + // set of non-overlap constraints in the case overlapping clusters + // (i.e., multiple inheritence). 1) We need to exclude the overlapping + // clusters from having non-overlap constraints. 2) We replace nodes + // with multiple parent clusters when enforcing non-overlap with their + // siblings and instead inforce non-overlap with the other clusters + // they are part of, since otherwise there is nothing stopping the + // other siblings of each cluster from overlapping each other. 3) We + // also need to enforce overlap still between the set of nodes replaced + // from each cluster in this way, since they may now be part of some + // new set. + std::set<ShapePair> m_cluster_cluster_overlap_exceptions; + std::map<unsigned, Cluster *> m_overlap_replacement_map; + std::set<unsigned> m_nodes_replaced_with_clusters; + + private: + friend class ConstrainedFDLayout; + friend class RootCluster; + + bool desiredBoundsSet; + vpsc::Rectangle desiredBounds; + + vpsc::Variable *vMin, *vMax; +}; + + +/** + * @brief Holds the cluster hierarchy specification for a diagram. + * + * This is not considered a cluster itself, but it records all the nodes in + * the diagram not contained within any clusters, as well as optionally a + * hierarchy of clusters. + * + * You can add clusters via addChildCluster() and nodes via addChildNode(). + * + * You can specify just the shapes contained in clusters, but not the nodes + * at this top level---the library will add any remaining nodes not appearing + * in the cluster hierarchy as children of the root cluster. + * + * It is possible to add a node as the child of two parent clusters. In this + * case, the clusters will overlap to contain this (and possibly other nodes). + * The library will warn you if you do this unless you have called the method + * setAllowsMultipleParents() to mark this intention. + * + * Be careful not to create cycles in the cluster hierarchy (i.e., to mark + * two clusters as children of each other. The library does not check for + * this and strange things may occur. + */ +class RootCluster : public Cluster +{ + public: + RootCluster(); + void computeBoundary(const vpsc::Rectangles& rs); + // There are just shapes at the top level, so + // effectively no clusters in the diagram scene. + bool flat(void) const + { + return clusters.empty(); + } + virtual void printCreationCode(FILE *fp) const; + virtual void outputToSVG(FILE *fp) const; + + //! Returns true if this cluster hierarchy allows multiple parents, + //! otherwise returns false. + //! + //! Defaults to false. If this is false, the library will display + //! warnings if you add a single node to multiple clusters. + //! + //! @sa setAllowsMultipleParents() + bool allowsMultipleParents(void) const; + + //! Set whether the cluster hierarchy should allow multiple parents. + //! + //! @param value New value for this setting. + //! + //! sa allowsMultipleParents() + void setAllowsMultipleParents(const bool value); + private: + void calculateClusterPathsToEachNode(size_t nodesCount); + + friend class ConstrainedFDLayout; + friend class Cluster; + + bool m_allows_multiple_parents; + + std::vector<ClustersList> m_cluster_vectors_leading_to_nodes; +}; + +/** + * @brief Defines a rectangular cluster, either variable-sized with floating + * sides or a fixed size based on a particular rectangle. + * + * The chosen constructor decides the type and behaviour of the cluster. + */ +class RectangularCluster : public Cluster +{ + public: + /** + * @brief A rectangular cluster of variable size that contains + * its children. + */ + RectangularCluster(); + /** + * @brief A fixed size rectangular cluster based on a particular + * rectangle. + * + * This rectangle might be constrained in the other ways like normal + * rectangles. + * + * @param[in] rectIndex The index of the rectangle that this cluster + * represents. + */ + RectangularCluster(unsigned rectIndex); + + /** + * @brief Sets the margin size for this cluster. + * + * This value represents the outer spacing that will be put between + * the cluster boundary on all sides and other clusters (plus their + * margin) and rectangles at the same level when non-overlap + * constraints are enabled. + * + * @param[in] margin The size of the margin for this cluster. + */ + void setMargin(double margin); + /** + * @brief Sets the margin box for this cluster. + * + * This box represents the outer spacing that will be put between + * the cluster boundary and other clusters (plus their margin) and + * rectangles at the same level when non-overlap constraints are + * enabled. + * + * @param[in] margin The box representing the margins for this + * cluster. + */ + void setMargin(const cola::Box margin); + /** + * @brief Returns the margin box for this cluster. + * + * @return The margin box for the cluster. + */ + cola::Box margin(void) const; + + /** + * @brief Sets the padding size for this cluster. + * + * This value represents the inner spacing that will be put between + * the cluster boundary and other child clusters (plus their margin) + * and child rectangles on all sides. + * + * @param[in] padding The size of the padding for this cluster. + */ + void setPadding(double padding); + /** + * @brief Sets the padding box for this cluster. + * + * This box represents the inner spacing that will be put between + * the cluster boundary and other child clusters (plus their margin) + * and child rectangles for each edge. + * + * @param[in] padding The Box representing padding values for this + * cluster. + */ + void setPadding(const cola::Box padding); + /** + * @brief Returns the padding box for this cluster. + * + * @return The padding box for the cluster. + */ + cola::Box padding(void) const; + +#ifndef SWIG + virtual ~RectangularCluster(); +#endif + void computeBoundary(const vpsc::Rectangles& rs); + virtual void countContainedNodes(std::vector<unsigned>& counts); + virtual void printCreationCode(FILE *fp) const; + virtual void outputToSVG(FILE *fp) const; + virtual void computeBoundingRect(const vpsc::Rectangles& rs); + virtual void addChildNode(unsigned index); + inline vpsc::Rectangle *getMinEdgeRect(const vpsc::Dim dim) + { + if (minEdgeRect[dim]) + { + delete minEdgeRect[dim]; + } + minEdgeRect[dim] = new vpsc::Rectangle(bounds); + + // Set the Min and Max positions to be the min minus an offset. + double edgePosition = minEdgeRect[dim]->getMinD(dim); + minEdgeRect[dim]->setMinD(dim, edgePosition - m_margin.min(dim)); + minEdgeRect[dim]->setMaxD(dim, edgePosition); + + return minEdgeRect[dim]; + } + + inline vpsc::Rectangle *getMaxEdgeRect(const vpsc::Dim dim) + { + if (maxEdgeRect[dim]) + { + delete maxEdgeRect[dim]; + } + maxEdgeRect[dim] = new vpsc::Rectangle(bounds); + + // Set the Min and Max positions to be the max plus an offset. + double edgePosition = maxEdgeRect[dim]->getMaxD(dim); + maxEdgeRect[dim]->setMaxD(dim, edgePosition + m_margin.max(dim)); + maxEdgeRect[dim]->setMinD(dim, edgePosition); + + return maxEdgeRect[dim]; + } + virtual bool clusterIsFromFixedRectangle(void) const; + int rectangleIndex(void) const; + + // For fixed sized clusters based on a rectangle, this method + // generates the constraints that attach the cluster edges to the + // centre position of the relevant rectangle. + void generateFixedRectangleConstraints( + cola::CompoundConstraints& idleConstraints, + vpsc::Rectangles& rc, vpsc::Variables (&vars)[2]) const; + + private: + vpsc::Rectangle *minEdgeRect[2]; + vpsc::Rectangle *maxEdgeRect[2]; + int m_rectangle_index; + Box m_margin; + Box m_padding; +}; + +/** + * @brief Defines a cluster that will be treated as a convex boundary around + * the child nodes and clusters. + */ +class ConvexCluster : public Cluster +{ + public: + void computeBoundary(const vpsc::Rectangles& rs); + virtual void printCreationCode(FILE *fp) const; + virtual void outputToSVG(FILE *fp) const; + + std::valarray<unsigned> hullRIDs; + std::valarray<unsigned char> hullCorners; +}; + + +} // namespace cola +#endif // COLA_CLUSTER_H diff --git a/src/3rdparty/adaptagrams/libcola/cola.cpp b/src/3rdparty/adaptagrams/libcola/cola.cpp new file mode 100644 index 0000000..739c6ea --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cola.cpp @@ -0,0 +1,700 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer +*/ + +#include <cmath> + +#include "libvpsc/assertions.h" +#include "libcola/commondefs.h" +#include "libcola/cola.h" +#include "libcola/conjugate_gradient.h" +#include "libcola/straightener.h" +#include "libcola/shortest_paths.h" +#include "libcola/cluster.h" + +using namespace std; +using namespace vpsc; +using straightener::generateClusterBoundaries; + +namespace cola { + +ConstrainedMajorizationLayout +::ConstrainedMajorizationLayout( + vector<Rectangle*>& rs, + const vector<Edge>& es, + RootCluster *clusterHierarchy, + const double idealLength, + EdgeLengths eLengths, + TestConvergence *doneTest, + PreIteration* preIteration, + bool useNeighbourStress) + : n(rs.size()), + lap2(valarray<double>(n*n)), + Dij(valarray<double>(n*n)), + tol(1e-7), + done(doneTest), + using_default_done(false), + preIteration(preIteration), + X(valarray<double>(n)), Y(valarray<double>(n)), + stickyNodes(false), + startX(valarray<double>(n)), startY(valarray<double>(n)), + constrainedLayout(false), + nonOverlappingClusters(false), + clusterHierarchy(clusterHierarchy), + gpX(nullptr), gpY(nullptr), + ccs(nullptr), + unsatisfiableX(nullptr), unsatisfiableY(nullptr), + avoidOverlaps(None), + straightenEdges(nullptr), + bendWeight(0.1), potBendWeight(0.1), + xSkipping(true), + scaling(true), + externalSolver(false), + majorization(true) +{ + if (done == nullptr) + { + done = new TestConvergence(); + using_default_done = true; + } + + boundingBoxes.resize(rs.size()); + copy(rs.begin(),rs.end(),boundingBoxes.begin()); + + done->reset(); + + COLA_ASSERT(!straightenEdges||straightenEdges->size()==es.size()); + + double** D=new double*[n]; + for(unsigned i=0;i<n;i++) { + D[i]=new double[n]; + } + + std::valarray<double> edgeLengths(eLengths.data(), eLengths.size()); + // Correct zero or negative entries in eLengths array. + for (size_t i = 0; i < edgeLengths.size(); ++i) + { + if (edgeLengths[i] <= 0) + { + fprintf(stderr, "Warning: ignoring non-positive length at index %d " + "in ideal edge length array.\n", (int) i); + edgeLengths[i] = 1; + } + } + + if (useNeighbourStress) { + for(unsigned i=0;i<n;i++) { + for(unsigned j=0;j<n;j++) { + D[i][j]=std::numeric_limits<double>::max(); + } + } + bool haveLengths = edgeLengths.size() == es.size(); + for (unsigned i = 0; i < es.size(); i++) { + unsigned source = es[i].first; + unsigned target = es[i].second; + D[source][target] = D[target][source] = (haveLengths ? edgeLengths[i] : 1.0); + } + } else { + shortest_paths::johnsons(n,D,es,edgeLengths); + //shortest_paths::neighbours(n,D,es,edgeLengths); + } + + edge_length = idealLength; + if(clusterHierarchy) { + for(Clusters::const_iterator i=clusterHierarchy->clusters.begin(); + i!=clusterHierarchy->clusters.end();i++) { + Cluster *c=*i; + for(set<unsigned>::iterator j=c->nodes.begin();j!=c->nodes.end();j++) { + for(set<unsigned>::iterator k=c->nodes.begin();k!=c->nodes.end();k++) { + unsigned a=*j, b=*k; + if(a==b) continue; + D[a][b]/=c->internalEdgeWeightFactor; + } + } + } + } + // Lij_{i!=j}=1/(Dij^2) + // + for(unsigned i = 0; i<n; i++) { + X[i]=rs[i]->getCentreX(); + Y[i]=rs[i]->getCentreY(); + double degree = 0; + for(unsigned j=0;j<n;j++) { + double d = edge_length * D[i][j]; + Dij[i*n + j] = d; + if(i==j) continue; + double lij=0; + if(d!=0 && !std::isinf(d)) { + lij=1./(d*d); + } + degree += lap2[i*n + j] = lij; + } + lap2[i*n + i]=-degree; + delete [] D[i]; + } + //GradientProjection::dumpSquareMatrix(Dij); + delete [] D; +} +// stickyNodes adds a small force attracting nodes +// back to their starting positions +void ConstrainedMajorizationLayout::setStickyNodes( + const double stickyWeight, + valarray<double> const & startX, + valarray<double> const & startY) { + COLA_ASSERT( startX.size()==n && startY.size()==n); + stickyNodes = true; + // not really constrained but we want to use GP solver rather than + // ConjugateGradient + constrainedLayout = true; + this->stickyWeight=stickyWeight; + this->startX = startX; + this->startY = startY; + for(unsigned i = 0; i<n; i++) { + lap2[i*n+i]-=stickyWeight; + } +} + +void ConstrainedMajorizationLayout::majorize( + valarray<double> const & Dij, GradientProjection* gp, + valarray<double>& coords, + valarray<double> const & startCoords) +{ + double L_ij,dist_ij,degree; + /* compute the vector b */ + /* multiply on-the-fly with distance-based laplacian */ + valarray<double> b(n); + for (unsigned i = 0; i < n; i++) { + b[i] = degree = 0; + for (unsigned j = 0; j < n; j++) { + if (j == i) continue; + dist_ij = euclidean_distance(i, j); + /* skip zero distances */ + if (dist_ij > 1e-30 && Dij[i*n+j] > 1e-30 && Dij[i*n+j] < 1e10) { + /* calculate L_ij := w_{ij}*d_{ij}/dist_{ij} */ + L_ij = 1.0 / (dist_ij * Dij[i*n+j]); + degree -= L_ij; + b[i] += L_ij * coords[j]; + } + } + if(stickyNodes) { + //double l = startCoords[i]-coords[i]; + //l/=10.; + //b[i]-=stickyWeight*(coords[i]+l); + b[i] -= stickyWeight*startCoords[i]; + } + b[i] += degree * coords[i]; + COLA_ASSERT(!std::isnan(b[i])); + } + if(constrainedLayout) { + //printf("GP iteration...\n"); + gp->solve(b,coords); + } else { + //printf("CG iteration...\n"); + conjugate_gradient(lap2, coords, b, n, tol, n); + } + moveBoundingBoxes(); +} +void ConstrainedMajorizationLayout::newton( + valarray<double> const & Dij, GradientProjection* gp, + valarray<double>& coords, + valarray<double> const & startCoords) +{ + COLA_UNUSED(startCoords); + /* compute the vector b */ + /* multiply on-the-fly with distance-based laplacian */ + valarray<double> b(n); + valarray<double> A(n*n); + for (unsigned i = 0; i < n; i++) { + b[i] = 0; + double Aii = 0; + for (unsigned j = 0; j < n; j++) { + if (j == i) continue; + double d = Dij[i*n+j]; + double l = euclidean_distance(i,j); + double dx = coords[i]-coords[j]; + double dy2 = l*l - dx*dx; + /* skip zero distances */ + if (l > 1e-30 + && d > 1e-30 && d < 1e10) { + if(d>80 && l > d) continue; + b[i]+=dx*(l-d)/(l*d*d); + Aii-=A[i*n+j]=(d*dy2/(l*l*l)-1)/(d*d); + } + } + A[i*n+i]=Aii; + } + if(constrainedLayout) { + //printf("GP iteration...\n"); + gp->solve(b,coords); + } else { + //printf("CG iteration...\n"); + /* + unsigned N=n-1; + valarray<double> b2(N); + valarray<double> A2(N*N); + valarray<double> x(N); + for(unsigned i=0;i<N;i++) { + b2=b[i]; + x=coords[i]; + for(unsigned j=0;j<N;j++) { + A2[i*N+j]=A[i*n+j]; + } + } + conjugate_gradient(A2, x, b2, N, tol, N); + */ + //valarray<double> x=coords; + //x-=x.sum()/n; + //conjugate_gradient(A, x, b, n, tol, n); + //double stepsize=0.5; + valarray<double> x=b; + // stepsize = g.g / (g A g) + double numerator = 0; + for(unsigned i=0;i<n;i++) { + numerator+=x[i]*x[i]; + } + double denominator = 0; + for(unsigned i=0;i<n;i++) { + double r=0; + for(unsigned j=0;j<n;j++) { + r+=A[i*n+j]*x[j]; + } + denominator+=r*x[i]; + } + double stepsize=numerator/(2*denominator); + double oldstress=compute_stress(Dij); + valarray<double> oldcoords=coords; + while(stepsize>0.00001) { + coords=oldcoords-stepsize*x; + double stress=compute_stress(Dij); + printf(" stress=%f, stepsize=%f\n",stress,stepsize); + if(oldstress>=stress) { + break; + } + coords=oldcoords; + stepsize*=0.5; + } + } + moveBoundingBoxes(); +} +inline double ConstrainedMajorizationLayout +::compute_stress(valarray<double> const &Dij) { + double sum = 0, d, diff; + for (unsigned i = 1; i < n; i++) { + for (unsigned j = 0; j < i; j++) { + d = Dij[i*n+j]; + if(!std::isinf(d)&&d!=numeric_limits<double>::max()) { + diff = d - euclidean_distance(i,j); + if(d>80&&diff<0) continue; + sum += diff*diff / (d*d); + } + } + if(stickyNodes) { + double l = startX[i]-X[i]; + sum += stickyWeight*l*l; + l = startY[i]-Y[i]; + sum += stickyWeight*l*l; + } + } + //printf("stress=%f\n",sum); + return sum; +} + +void ConstrainedMajorizationLayout::run(bool x, bool y) { + if(constrainedLayout) { + vector<vpsc::Rectangle*>* pbb = boundingBoxes.empty()?nullptr:&boundingBoxes; + SolveWithMosek mosek = Off; + if(externalSolver) mosek=Outer; + // scaling doesn't currently work with straighten edges because sparse + // matrix used with dummy nodes is not properly scaled at the moment. + if(straightenEdges) setScaling(false); + gpX=new GradientProjection( + HORIZONTAL,&lap2,tol,100,ccs,unsatisfiableX, + avoidOverlaps,clusterHierarchy,pbb,scaling,mosek); + gpY=new GradientProjection( + VERTICAL,&lap2,tol,100,ccs,unsatisfiableY, + avoidOverlaps,clusterHierarchy,pbb,scaling,mosek); + } + if(n>0) do { + // to enforce clusters with non-intersecting, convex boundaries we + // could create cluster boundaries here with chains of dummy nodes (a + // dummy node for each vertex of the convex hull) connected by dummy + // straightenEdges and we'd then continue on to straightenEdges below. + // This should work assuming we already have a feasible (i.e. non + // overlapping cluster) state. The former could be enforced by an + // earlier stage involving simple rectangular cluster boundaries. + vector<straightener::Edge*> cedges; + if(!straightenEdges && nonOverlappingClusters) { + straightenEdges = &cedges; + } + if(preIteration) { + if ((*preIteration)()) { + for(vector<Lock>::iterator l=preIteration->locks.begin(); + l!=preIteration->locks.end();l++) { + unsigned id=l->getID(); + double x=l->pos(HORIZONTAL), y=l->pos(VERTICAL); + X[id]=x; + Y[id]=y; + if(stickyNodes) { + startX[id]=x; + startY[id]=y; + } + boundingBoxes[id]->moveCentre(x,y); + if(constrainedLayout) { + gpX->fixPos(id,X[id]); + gpY->fixPos(id,Y[id]); + } + } + } else { break; } + } + /* Axis-by-axis optimization: */ + if(straightenEdges) { + if(x) straighten(*straightenEdges,HORIZONTAL); + if(y) straighten(*straightenEdges,VERTICAL); + } else { + if(majorization) { + if(x) majorize(Dij,gpX,X,startX); + if(y) majorize(Dij,gpY,Y,startY); + } else { + if(x) newton(Dij,gpX,X,startX); + if(y) newton(Dij,gpY,Y,startY); + } + } + if(clusterHierarchy) { + for(Clusters::iterator c=clusterHierarchy->clusters.begin(); + c!=clusterHierarchy->clusters.end();c++) { + (*c)->computeBoundary(boundingBoxes); + } + } + if(preIteration && constrainedLayout) { + for(vector<Lock>::iterator l=preIteration->locks.begin(); + l!=preIteration->locks.end();l++) { + gpX->unfixPos(l->getID()); + gpY->unfixPos(l->getID()); + } + } + } while(!(*done)(compute_stress(Dij),X,Y)); +} +double ConstrainedMajorizationLayout::computeStress() { + return compute_stress(Dij); +} +void ConstrainedMajorizationLayout::runOnce(bool x, bool y) { + if(constrainedLayout) { + vector<vpsc::Rectangle*>* pbb = boundingBoxes.empty()?nullptr:&boundingBoxes; + SolveWithMosek mosek = Off; + if(externalSolver) mosek=Outer; + // scaling doesn't currently work with straighten edges because sparse + // matrix used with dummy nodes is not properly scaled at the moment. + if(straightenEdges) setScaling(false); + gpX=new GradientProjection( + HORIZONTAL,&lap2,tol,100,ccs,unsatisfiableX, + avoidOverlaps,clusterHierarchy,pbb,scaling,mosek); + gpY=new GradientProjection( + VERTICAL,&lap2,tol,100,ccs,unsatisfiableY, + avoidOverlaps,clusterHierarchy,pbb,scaling,mosek); + } + if(n>0) { + // to enforce clusters with non-intersecting, convex boundaries we + // could create cluster boundaries here with chains of dummy nodes (a + // dummy node for each vertex of the convex hull) connected by dummy + // straightenEdges and we'd then continue on to straightenEdges below. + // This should work assuming we already have a feasible (i.e. non + // overlapping cluster) state. The former could be enforced by an + // earlier stage involving simple rectangular cluster boundaries. + vector<straightener::Edge*> cedges; + if(!straightenEdges && nonOverlappingClusters) { + straightenEdges = &cedges; + } + if(preIteration) { + if ((*preIteration)()) { + for(vector<Lock>::iterator l=preIteration->locks.begin(); + l!=preIteration->locks.end();l++) { + unsigned id=l->getID(); + double x=l->pos(HORIZONTAL), y=l->pos(VERTICAL); + X[id]=x; + Y[id]=y; + if(stickyNodes) { + startX[id]=x; + startY[id]=y; + } + boundingBoxes[id]->moveCentre(x,y); + if(constrainedLayout) { + gpX->fixPos(id,X[id]); + gpY->fixPos(id,Y[id]); + } + } + } else { return; } + } + /* Axis-by-axis optimization: */ + if(straightenEdges) { + if(x) straighten(*straightenEdges,HORIZONTAL); + if(y) straighten(*straightenEdges,VERTICAL); + } else { + if(majorization) { + if(x) majorize(Dij,gpX,X,startX); + if(y) majorize(Dij,gpY,Y,startY); + } else { + if(x) newton(Dij,gpX,X,startX); + if(y) newton(Dij,gpY,Y,startY); + } + } + if(clusterHierarchy) { + for(Clusters::iterator c=clusterHierarchy->clusters.begin(); + c!=clusterHierarchy->clusters.end();c++) { + (*c)->computeBoundary(boundingBoxes); + } + } + if(preIteration && constrainedLayout) { + for(vector<Lock>::iterator l=preIteration->locks.begin(); + l!=preIteration->locks.end();l++) { + gpX->unfixPos(l->getID()); + gpY->unfixPos(l->getID()); + } + } + } +} +void ConstrainedMajorizationLayout::straighten(vector<straightener::Edge*>& sedges, Dim dim) { + GradientProjection * gp; + valarray<double>* coords; + valarray<double>* startCoords; + if(dim==HORIZONTAL) { + gp=gpX; + coords=&X; + startCoords=&startX; + } else { + gp=gpY; + coords=&Y; + startCoords=&startY; + } + vector<straightener::Node*> snodes; + if(dim==HORIZONTAL) { + Rectangle::setXBorder(0.0001); + } + for (unsigned i=0;i<n;i++) { + snodes.push_back(new straightener::Node(i,boundingBoxes[i])); + } + if(dim==HORIZONTAL) { + Rectangle::setXBorder(0); + } + for (unsigned i=n;i<gp->getNumStaticVars();i++) { + // insert some dummy nodes + snodes.push_back(new straightener::Node(i,-100,-100)); + } + vector<straightener::Cluster*> sclusters; + + if(nonOverlappingClusters && clusterHierarchy) { + generateClusterBoundaries(dim,snodes,sedges,boundingBoxes, + *clusterHierarchy,sclusters); + } + vector<SeparationConstraint*> cs; + straightener::generateConstraints(dim,snodes,sedges,cs,xSkipping); + straightener::LinearConstraints linearConstraints; + for(unsigned i=0;i<sedges.size();i++) { + sedges[i]->nodePath(snodes,!nonOverlappingClusters); + vector<unsigned>& path=sedges[i]->path; + vector<unsigned>& activePath=sedges[i]->activePath; + // take u and v as the ends of the line + // unsigned u=path[0]; + // unsigned v=path[path.size()-1]; + double total_length=0; + for(unsigned j=1;j<path.size();j++) { + unsigned u=path[j-1], v=path[j]; + total_length+=snodes[u]->euclidean_distance(snodes[v]); + } + // keep potential bends straight + for(unsigned j=1;j<activePath.size();j++) { + unsigned uj=activePath[j-1], vj=activePath[j]; + unsigned u=path[uj], v=path[vj]; + for(unsigned k=uj+1;k<vj;k++) { + unsigned b=path[k]; + // might be useful to have greater weight for potential bends than actual bends + linearConstraints.push_back(new straightener::LinearConstraint( + *snodes[u],*snodes[v],*snodes[b],-potBendWeight)); + } + } + // straighten actual bends + for(unsigned j=1;j<activePath.size()-1;j++) { + unsigned u=path[activePath[j-1]], + b=path[activePath[j]], + v=path[activePath[j+1]]; + linearConstraints.push_back(new straightener::LinearConstraint( + *snodes[u],*snodes[v],*snodes[b],-bendWeight)); + } + } + //std::cout << (dim==HORIZONTAL?"X":"Y") << " snodes.size "<<snodes.size()<< " n="<<n<<std::endl; + //std::cout << "Generated "<<linearConstraints.size()<< " linear constraints"<<std::endl; + SparseMap Q(snodes.size()); + for(straightener::LinearConstraints::iterator i=linearConstraints.begin(); + i!= linearConstraints.end();i++) { + straightener::LinearConstraint* c=*i; + Q(c->u,c->u)+=c->w*c->duu; + Q(c->u,c->v)+=c->w*c->duv; + Q(c->u,c->b)+=c->w*c->dub; + Q(c->v,c->u)+=c->w*c->duv; + Q(c->v,c->v)+=c->w*c->dvv; + Q(c->v,c->b)+=c->w*c->dvb; + Q(c->b,c->b)+=c->w*c->dbb; + Q(c->b,c->u)+=c->w*c->dub; + Q(c->b,c->v)+=c->w*c->dvb; + } + double boundaryWeight = 0.0001; + for(unsigned i=0;i<sclusters.size();i++) { + // for each cluster boundary chain create an attractive force between + // each pair of adjacent nodes + straightener::Cluster* c = sclusters[i]; + for(unsigned j=0;j<c->boundary.size();j++) { + straightener::Edge* e = c->boundary[j]; + Q(e->startNode,e->endNode)+=boundaryWeight; + Q(e->endNode,e->startNode)+=boundaryWeight; + Q(e->startNode,e->startNode)-=boundaryWeight; + Q(e->endNode,e->endNode)-=boundaryWeight; + } + } + constrainedLayout = true; + SparseMatrix sparseQ(Q); + gp->straighten(&sparseQ,cs,snodes); + //return; + majorize(Dij,gp,*coords,*startCoords); + valarray<double> const & r=gp->getFullResult(); + for(unsigned i=0;i<snodes.size();i++) { + snodes[i]->pos[dim] = r[i]; + } + for(unsigned i=0;i<sedges.size();i++) { + sedges[i]->createRouteFromPath(snodes); + sedges[i]->dummyNodes.clear(); + sedges[i]->path.clear(); + } + for(unsigned i=0;i<sclusters.size();i++) { + straightener::Cluster *sc = sclusters[i]; + //sc->updateActualBoundary(); + delete sc; + } + for(unsigned i=0;i<cs.size();i++) { + delete cs[i]; + } + for(unsigned i=0;i<linearConstraints.size();i++) { + delete linearConstraints[i]; + } + for(unsigned i=0;i<snodes.size();i++) { + delete snodes[i]; + } +} + +Rectangle bounds(vector<Rectangle*>& rs) { + COLA_ASSERT(!rs.empty()); + + double left = rs[0]->getMinX(), right = rs[0]->getMaxX(), + top = rs[0]->getMinY(), bottom = rs[0]->getMaxY(); + + for(unsigned i = 1; i < rs.size(); i++) { + left = min(left,rs[i]->getMinX()); + right = max(right,rs[i]->getMaxX()); + top = min(top,rs[i]->getMinY()); + bottom = max(bottom,rs[i]->getMaxY()); + } + return Rectangle(left, right, top, bottom); +} + +#if 0 + void removeClusterOverlap(RootCluster& clusterHierarchy, vpsc::Rectangles& rs, Locks& locks, vpsc::Dim dim) { + if(clusterHierarchy.nodes.size()>0 || clusterHierarchy.clusters.size()>0) { + vpsc::Variables vars; + vpsc::Constraints cs; + for(unsigned i=0;i<rs.size();i++) { + vars.push_back(new vpsc::Variable(i, rs[i]->getCentreD(dim))); + } + + clusterHierarchy.computeBoundingRect(rs); + clusterHierarchy.createVars(dim,rs,vars); + clusterHierarchy.generateNonOverlapConstraints(dim, cola::Both, rs, vars, cs); + + /* + if(dim==vpsc::HORIZONTAL) { + vpsc::Rectangle::setXBorder(0.001); + // use rs->size() rather than n because some of the variables may + // be dummy vars with no corresponding rectangle + generateXConstraints(rs,vars,cs,true); + vpsc::Rectangle::setXBorder(0); + } else { + generateYConstraints(rs,vars,cs); + } + */ + for(Locks::iterator l=locks.begin(); + l!=locks.end();l++) { + unsigned id=l->getID(); + double x=l->pos(HORIZONTAL), y=l->pos(VERTICAL); + Variable* v=vars[id]; + v->desiredPosition = (dim==vpsc::HORIZONTAL)?x:y; + v->weight = 1000; + } + /* + vpsc::Solver s(vars,cs); + try { + s.satisfy(); + } catch(const char* e) { + cerr << "ERROR from solver in GraphData::removeOverlap : " << e << endl; + } + */ + vpsc::IncSolver s(vars,cs); + try { + s.solve(); + } catch(const char* e) { + cerr << "ERROR from solver in GraphData::removeOverlap : " << e << endl; + } + clusterHierarchy.updateBounds(dim); + /* + for(unsigned i=0;i<cs.size();++i) { + if(cs[i]->unsatisfiable) { + cout << "Unsatisfiable constraint: " << *cs[i] << endl; + } + } + */ + for(unsigned i=0;i<rs.size();i++) { + rs[i]->moveCentreD(dim,vars[i]->finalPosition); + } + for(Locks::iterator l=locks.begin(); + l!=locks.end();l++) { + //unsigned id=l->getID(); + } + for_each(vars.begin(),vars.end(),delete_object()); + for_each(cs.begin(),cs.end(),delete_object()); + } + } + void removeClusterOverlapFast(RootCluster& clusterHierarchy, vpsc::Rectangles& rs, Locks& locks) { + removeClusterOverlap(clusterHierarchy, rs, locks, vpsc::HORIZONTAL); + removeClusterOverlap(clusterHierarchy, rs, locks, vpsc::VERTICAL); + } +#endif + + ConstrainedMajorizationLayout* simpleCMLFactory( + vpsc::Rectangles& rs, + std::vector<Edge> const & es, + RootCluster* clusterHierarchy, + const double idealLength, + bool useNeighbourStress + ) { + cola::EdgeLengths eLengths; + for(size_t i = 0; i < es.size(); ++i) { + eLengths.push_back(1); + } + return new ConstrainedMajorizationLayout(rs, es, clusterHierarchy, idealLength, + eLengths, nullptr, nullptr, useNeighbourStress); + }; + +} // namespace cola diff --git a/src/3rdparty/adaptagrams/libcola/cola.h b/src/3rdparty/adaptagrams/libcola/cola.h new file mode 100644 index 0000000..40043cd --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cola.h @@ -0,0 +1,1002 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2015 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer + * Michael Wybrow +*/ + +#ifndef COLA_H +#define COLA_H + +#include <utility> +#include <iterator> +#include <vector> +#include <valarray> +#include <algorithm> +#include <cmath> +#include <iostream> + +#include "libcola/gradient_projection.h" +#include "libcola/cluster.h" +#include "libcola/straightener.h" +#include "libcola/exceptions.h" +#include "libcola/pseudorandom.h" + +namespace vpsc { class Rectangle; } +namespace topology { + class ColaTopologyAddon; +} +namespace dialect { + class Graph; +} + + +/** + * @namespace cola + * @brief libcola: Force-directed network layout subject to + * separation constraints library. + * + * You should use COLA via an instance of the ConstrainedFDLayout class. +*/ +namespace cola { + +class NonOverlapConstraints; +class NonOverlapConstraintExemptions; + +//! @brief A vector of node Indexes. +typedef std::vector<unsigned> NodeIndexes; + +//! @brief A vector of NodeIndexes. +typedef std::vector<NodeIndexes> ListOfNodeIndexes; + +//! Edges are simply a pair of indices to entries in the Node vector +typedef std::pair<unsigned, unsigned> Edge; + +//! EdgeLengths is a vector of ideal lengths for edges corresponding to +//! edges in the edge list. +typedef std::vector<double> EdgeLengths; +#define StandardEdgeLengths EdgeLengths() + +/** + * @brief A Lock specifies a required position for a node. + */ +class Lock { +public: + Lock() {} + /** + * @brief Constructs a Lock object for a given node and position. + * + * @param[in] id The index of the node in the Rectangles vector. + * @param[in] X The node's fixed position in the x-dimension. + * @param[in] Y The node's fixed position in the y-dimension. + */ + Lock(unsigned id, double X, double Y) : id(id), x(X), y(Y) { + } + unsigned getID() const { + return id; + } + double pos(vpsc::Dim dim) const { + return dim==vpsc::HORIZONTAL?x:y; + } +private: + unsigned id; + double x; + double y; +}; +//! @brief A vector of Lock objects. +typedef std::vector<cola::Lock> Locks; + +/** + * @brief A Resize specifies a new required bounding box for a node. + */ +class Resize { +public: + Resize() {} + /** + * @brief Constructs a Resize object for a given node and it's new + * bounding box. + * + * @param[in] id The index of the node in the Rectangles vector. + * @param[in] x The minimum horizontal value for the node's new + * bounding box. + * @param[in] y The minimum vertical value for the node's new + * bounding box. + * @param[in] w The width value for the node's new bounding box. + * @param[in] h The height value for the node's new bounding box. + */ + Resize(unsigned id, double x, double y, double w, double h) + : id(id), target(x,x+w,y,y+h) {} + unsigned getID() const { + return id; + } + const vpsc::Rectangle* getTarget() const { + return ⌖ + } +private: + unsigned id; + vpsc::Rectangle target; +}; +//! @brief A vector of Resize objects. +typedef std::vector<cola::Resize> Resizes; + +/* + * Setting a desired position for a node adds a term to the goal function + * drawing the node towards that desired position + */ +struct DesiredPosition { + unsigned id; + double x; + double y; + double weight; +}; +typedef std::vector<cola::DesiredPosition> DesiredPositions; + +/* + * desired positions which should override those computed by applying forces + * are passed in for a set of nodes. The first entry is the Node->id, the + * second is the desired position. + */ +typedef std::pair<unsigned,double> DesiredPositionInDim; +typedef std::vector<DesiredPositionInDim> DesiredPositionsInDim; + +/** + * @brief A default functor that is called before each iteration in the + * main loop of the ConstrainedFDLayout::run() method. + * + * Override the operator() for things like locking the position of nodes + * for the duration of the iteration. + * + * If the operator() returns false the subsequent iterations are + * abandoned, i.e., layout ends immediately. You can make it return true + * when a user-interrupt is detected, for instance. + */ +class PreIteration { +public: + /** + * @brief Constructs a PreIteration object that handles locking and + * resizing of nodes. + * + * @param[in] locks A list of nodes (by index) and positions at which + * they should be locked. + * @param[in] resizes A list of nodes (by index) and required dimensions + * for their bounding rects to be resized to. + */ + PreIteration( + Locks& locks=__locksNotUsed, + Resizes& resizes=__resizesNotUsed) + : locks(locks) + , resizes(resizes) + , changed(true) {} + PreIteration(Resizes& resizes) + : locks(__locksNotUsed) + , resizes(resizes) + , changed(true) {} + +// To prevent C++ objects from being destroyed in garbage collected languages +// when the libraries are called from SWIG, we hide the declarations of the +// destructors and prevent generation of default destructors. +#ifndef SWIG + virtual ~PreIteration() {} +#endif + virtual bool operator()() { return true; } + Locks& locks; + Resizes& resizes; + bool changed; +private: + static Locks __locksNotUsed; + static Resizes __resizesNotUsed; +}; + +/** + * @brief A default functor that is called after each iteration of the layout + * algorithm. + * + * You can either instantiate ConstrainedFDLayout with an instance of this + * class setting the tolerance and maxiterations as desired, or create a + * derived class implementing the operator() to do your own convergence test, + * or create your own operator() that calls the TestConvergence::operator() in + * order to do any other post processing you might need, e.g., to animate + * changes. + */ +class TestConvergence { +public: + double old_stress; + TestConvergence(const double tol = 1e-4, const unsigned maxiterations = 100) + : tolerance(tol), + maxiterations(maxiterations) + { reset(); } + virtual ~TestConvergence() {} + +public: + virtual bool operator()(const double new_stress, std::valarray<double> & X, std::valarray<double> & Y) + { + COLA_UNUSED(X); + COLA_UNUSED(Y); + + iterations++; + //std::cout<<"iteration="<<iterations<<", old_stress="<<old_stress<<", new_stress="<<new_stress<<std::endl; + if (old_stress == DBL_MAX) { + old_stress = new_stress; + return iterations >= maxiterations; + } + // converged if relative decrease in stress falls below threshold + // or if stress increases (shouldn't happen for straight majorization) + bool converged = + (old_stress - new_stress) / (new_stress + 1e-10) < tolerance + || iterations > maxiterations; + old_stress = new_stress; + return converged; + } + void reset() { + old_stress = DBL_MAX; + iterations = 0; + } + const double tolerance; + const unsigned maxiterations; + unsigned iterations; +}; + +/** + * @brief Implements the Constrained Majorization graph layout algorithm + * (deprecated). + * + * The optimisation method used is "stress majorization", where a sequence of + * quadratic functions which strictly bound the stress from above, is solved + * to monotonically reduce the stress (by iteratively changing the + * configuration of nodes). + * + * Once the problem has been set up, call run() or runOnce() to run the + * layout algorithm. + * + * @note We recommend the use of ConstrainedFDLayout instead of this class. + * ConstrainedFDLayout tends to produce better results and has more + * features. We are no longer working on ConstrainedMajorizationLayout. + */ +class ConstrainedMajorizationLayout { +public: + /** + * @brief Constructs a constrained majorization layout instance. + * + * @param[in] rs Bounding boxes of nodes at their initial positions. + * @param[in] es Simple pair edges, giving indices of the start and end + * nodes in rs. + * @param[in] clusterHierarchy A pointer to a RootCluster object defining + * the cluster hierarchy (optional). + * @param[in] idealLength Aa scalar modifier of ideal edge lengths in + * eLengths. + * @param[in] eLengths Individual ideal lengths for edges. + * The actual ideal length used for the ith edge is + * idealLength*eLengths[i], or if eLengths is empty + * then just idealLength is used (i.e., eLengths[i] + * is assumed to be 1). + * @param[in] done A test of convergence operation called at the end of + * each iteration (optional). + * @param[in] preIteration An operation called before each iteration + * (optional). + */ + ConstrainedMajorizationLayout( + vpsc::Rectangles& rs, + std::vector<Edge> const & es, + RootCluster* clusterHierarchy, + const double idealLength, + EdgeLengths eLengths = StandardEdgeLengths, + TestConvergence *doneTest = nullptr, + PreIteration* preIteration=nullptr, + bool useNeighbourStress = false); + /** + * @brief Specify a set of compound constraints to apply to the layout. + * + * @param[in] ccs The compound constraints. + */ + void setConstraints(cola::CompoundConstraints* ccs) { + constrainedLayout = true; + this->ccs=ccs; + } + + void setConstraintsVector(cola::CompoundConstraints& ccs) { + constrainedLayout = true; + cola::CompoundConstraints *ccsp = new cola::CompoundConstraints; + for (size_t i = 0; i < ccs.size(); ++i) { + ccsp->push_back(ccs.at(i)); + } + this->ccs=ccsp; + } + + /** + * @brief Register to receive information about unsatisfiable constraints. + * + * In the case of unsatisifiable constraints, the solver will drop + * unsatisfiable constraints of lowest priority. Information about these + * will be written to these lists after each iteration of constrained + * layout. + * + * param[out] unsatisfiableX A pointer to an UnsatisfiableConstraintInfos + * object that will be used to record + * unsatisfiable constraints in the x-dimension. + * param[out] unsatisfiableY A pointer to an UnsatisfiableConstraintInfos + * object that will be used to record + * unsatisfiable constraints in the y-dimension. + */ + void setUnsatisfiableConstraintInfo( + UnsatisfiableConstraintInfos *unsatisfiableX, + UnsatisfiableConstraintInfos *unsatisfiableY) { + this->unsatisfiableX = unsatisfiableX; + this->unsatisfiableY = unsatisfiableY; + } + /** + * Sticky nodes causes nodes to spring back to (startX,startY) when + * unconstrained. + */ + void setStickyNodes(const double stickyWeight, + std::valarray<double> const & startX, + std::valarray<double> const & startY); + + /** + * Scaling speeds up the solver by conditioning the quadratic terms matrix. + */ + void setScaling(bool scaling) { + this->scaling=scaling; + } + /** + * Says that the Mosek optimisation library should be used to solve the + * quadratic programs rather than the libvpsc solver. + */ + void setExternalSolver(bool externalSolver) { + this->externalSolver=externalSolver; + } + /** + * At each iteration of layout, generate constraints to avoid overlaps. + * If bool horizontal is true, all overlaps will be resolved horizontally, + * otherwise some overlaps will be left to be resolved vertically where + * doing so leads to less displacement + */ + void setAvoidOverlaps(bool horizontal = false) { + constrainedLayout = true; + this->avoidOverlaps = horizontal ? Horizontal : Both; + } + /** + * Add constraints to prevent clusters overlapping. + */ + void setNonOverlappingClusters() { + constrainedLayout = true; + nonOverlappingClusters = true; + } + /** + * For the specified edges (with routings), generate dummy vars and + * constraints to try and straighten them. bendWeight controls how hard we + * try to straighten existing bends potBendWeight controls how much we try + * to keep straight edges straight + */ + void setStraightenEdges(std::vector<straightener::Edge*>* straightenEdges, + double bendWeight = 0.01, double potBendWeight = 0.1, + bool xSkipping = true) { + for(std::vector<straightener::Edge*>::const_iterator e=straightenEdges->begin(); + e!=straightenEdges->end();e++) { + (*e)->rerouteAround(boundingBoxes); + } + constrainedLayout = true; + this->xSkipping = xSkipping; + this->straightenEdges = straightenEdges; + this->bendWeight = bendWeight; + this->potBendWeight = potBendWeight; + } + /** + * Update position of bounding boxes. + */ + void moveBoundingBoxes() { + for(unsigned i=0;i<n;i++) { + boundingBoxes[i]->moveCentre(X[i],Y[i]); + } + } + + ~ConstrainedMajorizationLayout() { + if (using_default_done) + { + delete done; + } + + if(constrainedLayout) { + delete gpX; + delete gpY; + } + } + /** + * @brief Implements the main layout loop, taking descent steps until + * stress is no-longer significantly reduced. + * + * @param[in] x If true, layout will be performed in x-dimension + * (default: true). + * @param[in] y If true, layout will be performed in y-dimension + * (default: true). + */ + void run(bool x=true, bool y=true); + /** + * @brief Same as run(), but only applies one iteration. + * + * This may be useful here it's too hard to implement a call-back + * (e.g., in java apps). + * + * @param[in] x If true, layout will be performed in x-dimension + * (default: true). + * @param[in] y If true, layout will be performed in y-dimension + * (default: true). + */ + void runOnce(bool x=true, bool y=true); + void straighten(std::vector<straightener::Edge*>&, vpsc::Dim); + void setConstrainedLayout(bool c) { + constrainedLayout=c; + } + double computeStress(); +private: + double euclidean_distance(unsigned i, unsigned j) { + return sqrt( + (X[i] - X[j]) * (X[i] - X[j]) + + (Y[i] - Y[j]) * (Y[i] - Y[j])); + } + double compute_stress(std::valarray<double> const & Dij); + void majorize(std::valarray<double> const & Dij,GradientProjection* gp, std::valarray<double>& coords, std::valarray<double> const & startCoords); + void newton(std::valarray<double> const & Dij,GradientProjection* gp, std::valarray<double>& coords, std::valarray<double> const & startCoords); + unsigned n; //< number of nodes + //std::valarray<double> degrees; + std::valarray<double> lap2; //< graph laplacian + std::valarray<double> Q; //< quadratic terms matrix used in computations + std::valarray<double> Dij; //< all pairs shortest path distances + double tol; //< convergence tolerance + TestConvergence *done; //< functor used to determine if layout is finished + bool using_default_done; // Whether we allocated a default TestConvergence object. + PreIteration* preIteration; //< client can use this to create locks on nodes + vpsc::Rectangles boundingBoxes; //< node bounding boxes + /* + * stickyNodes controls whether nodes are attracted to their starting + * positions (at time of ConstrainedMajorizationLayout instantiation) + * stored in startX, startY + */ + std::valarray<double> X, Y; + bool stickyNodes; + double stickyWeight; + std::valarray<double> startX; + std::valarray<double> startY; + double edge_length; + bool constrainedLayout; + bool nonOverlappingClusters; + /* + * A cluster is a set of nodes that are somehow semantically grouped + * and should therefore be kept together a bit more tightly than, and + * preferably without overlapping, the rest of the graph. + * + * We achieve this by augmenting the L matrix with stronger attractive + * forces between all members of a cluster (other than the root) + * and by maintaining a (preferably convex) hull around those + * constituents which, using constraints and dummy variables, is + * prevented from overlapping other parts of the graph. + * + * Clusters are defined over the graph in a hierarchy starting with + * a single root cluster. + * + * Need to: + * - augment Lap matrix with intra cluster forces + * - compute convex hull of each cluster + * - from convex hull generate "StraightenEdges" + */ + RootCluster *clusterHierarchy; + GradientProjection *gpX, *gpY; + cola::CompoundConstraints *ccs; + UnsatisfiableConstraintInfos *unsatisfiableX, *unsatisfiableY; + NonOverlapConstraintsMode avoidOverlaps; + std::vector<straightener::Edge*>* straightenEdges; + + double bendWeight, potBendWeight; + /* + * determines whether we should leave some overlaps to be resolved + * vertically when generating straightening constraints in the x-dim + */ + bool xSkipping; + /* + * when using the gradient projection optimisation method, the following + * controls whether the problem should be preconditioned by affine scaling + */ + bool scaling; + /* + * if the Mosek quadratic programming environment is available it may be + * used to solve each iteration of stress majorization... slow but useful + * for testing + */ + bool externalSolver; + bool majorization; +}; + +vpsc::Rectangle bounds(vpsc::Rectangles& rs); + +class ConstrainedFDLayout; + +/** + * @brief Interface for writing COLA addons to handle topology preserving + * layout. + */ +class TopologyAddonInterface +{ + public: + TopologyAddonInterface() + { + } + + virtual ~TopologyAddonInterface() + { + } + + virtual TopologyAddonInterface *clone(void) const + { + return new TopologyAddonInterface(*this); + } + + virtual void freeAssociatedObjects(void) + { + } + + virtual void handleResizes(const Resizes& resizeList, unsigned n, + std::valarray<double>& X, std::valarray<double>& Y, + cola::CompoundConstraints& ccs, + vpsc::Rectangles& boundingBoxes, + cola::RootCluster* clusterHierarchy) + { + COLA_UNUSED(resizeList); + COLA_UNUSED(n); + COLA_UNUSED(X); + COLA_UNUSED(Y); + COLA_UNUSED(ccs); + COLA_UNUSED(boundingBoxes); + COLA_UNUSED(clusterHierarchy); + } + virtual void computePathLengths(unsigned short** G) + { + COLA_UNUSED(G); + } + virtual double computeStress(void) const + { + return 0; + } + virtual bool useTopologySolver(void) const + { + return false; + } + virtual void makeFeasible(bool generateNonOverlapConstraints, + vpsc::Rectangles& boundingBoxes, + cola::RootCluster* clusterHierarchy) + { + COLA_UNUSED(generateNonOverlapConstraints); + COLA_UNUSED(boundingBoxes); + COLA_UNUSED(clusterHierarchy); + } + virtual void moveTo(const vpsc::Dim dim, vpsc::Variables& vs, + vpsc::Constraints& cs, std::valarray<double> &coords, + cola::RootCluster* clusterHierarchy) + { + COLA_UNUSED(dim); + COLA_UNUSED(vs); + COLA_UNUSED(cs); + COLA_UNUSED(coords); + COLA_UNUSED(clusterHierarchy); + } + virtual double applyForcesAndConstraints(ConstrainedFDLayout *layout, + const vpsc::Dim dim, std::valarray<double>& g, + vpsc::Variables& vs, vpsc::Constraints& cs, + std::valarray<double> &coords, + DesiredPositionsInDim& des, double oldStress) + { + COLA_UNUSED(layout); + COLA_UNUSED(dim); + COLA_UNUSED(g); + COLA_UNUSED(vs); + COLA_UNUSED(cs); + COLA_UNUSED(coords); + COLA_UNUSED(des); + COLA_UNUSED(oldStress); + return 0; + } +}; + + +/** + * @brief Implements a constrained force-directed layout algorithm. + * + * This method is based on a non-linear gradient projection technique. + * Conceptually it's similar to a force directed method like + * Fruchterman-Reingold---but using a more principled goal function and + * optimisation techniques. + */ +class ConstrainedFDLayout { +public: + /** + * @brief Constructs a constrained force-directed layout instance. + * + * If an empty edges (es) vector is passed to the constructor, then + * constraint satisfaction will be performed, but no force-directed + * layout. In this case, idealLength and eLengths have no effect. + * + * Conversely, if no constraints or clusters are specified and no overlap + * prevention is enabled, but edge info is given, then pure force-directed + * layout will be performed. + * + * @param[in] rs Bounding boxes of nodes at their initial positions. + * @param[in] es Simple pair edges, giving indices of the start and end + * nodes in rs. + * @param[in] idealLength A scalar modifier of ideal edge lengths in + * eLengths or of 1 if no ideal lengths are + * specified. + * @param[in] eLengths Individual ideal lengths for edges. + * The actual ideal length used for the ith edge is + * idealLength*eLengths[i], or if eLengths is nullptr a + * then just idealLength is used (i.e., eLengths[i] + * is assumed to be 1). + * @param[in] done A test of convergence operation called at the end of + * each iteration (optional). If not given, uses a + * default TestConvergence object. + * @param[in] preIteration An operation called before each iteration + * (optional). + */ + ConstrainedFDLayout( + const vpsc::Rectangles& rs, + const std::vector<cola::Edge>& es, + const double idealLength, + const EdgeLengths& eLengths = StandardEdgeLengths, + TestConvergence* doneTest = nullptr, + PreIteration* preIteration = nullptr); + ~ConstrainedFDLayout(); + + /** + * @brief Implements the main layout loop, taking descent steps until + * stress is no-longer significantly reduced. + * + * @param[in] x If true, layout will be performed in x-dimension + * (default: true). + * @param[in] y If true, layout will be performed in y-dimension + * (default: true). + */ + void run(bool x=true, bool y=true); + + /** + * @brief Same as run(), but only applies one iteration. + * + * This may be useful here it's too hard to implement a call-back + * (e.g., in java apps). + * + * @param[in] x If true, layout will be performed in x-dimension + * (default: true). + * @param[in] y If true, layout will be performed in y-dimension + * (default: true). + */ + void runOnce(bool x=true, bool y=true); + + /** + * @brief Specify a set of compound constraints to apply to the layout. + * + * @param[in] ccs The compound constraints. + */ + void setConstraints(const cola::CompoundConstraints& ccs); + + /** + * @brief Specifies whether non-overlap constraints should be + * automatically generated between all nodes, as well as any + * exemptions to this. + * + * The optional second parameter indicates groups of nodes that should be + * exempt from having non-overlap constraints generated between each other. + * For example, you might want to do this for nodes representing ports, or + * the child nodes in a particular cluster. + * + * @param[in] avoidOverlaps New boolean value for this option. + * @param[in] listOfNodeGroups A list of groups of node indexes which will + * not have non-overlap constraints generated + * between each other. + */ + void setAvoidNodeOverlaps(bool avoidOverlaps, + ListOfNodeIndexes listOfNodeGroups = + ListOfNodeIndexes()); + + /** + * @brief Set an addon for doing topology preserving layout. + * + * It is expected that you would use the topology::ColaTopologyAddon() + * from libtopology rather than write your own. This is done so that + * libcola does not have to depend on libtopology. + * + * @param[in] topology Instance of a class implementing the + * TopologyAddonInterface. + * @sa topology::ColaTopologyAddon + */ + void setTopology(TopologyAddonInterface *topology); + TopologyAddonInterface *getTopology(void); + + void setDesiredPositions(DesiredPositions *desiredPositions); + + /** + * @brief Specifies an optional hierarchy for clustering nodes. + * + * @param[in] hierarchy A pointer to a RootCluster object defining the + * the cluster hierarchy (optional). + */ + void setClusterHierarchy(RootCluster *hierarchy) + { + clusterHierarchy = hierarchy; + } + /** + * @brief Register to receive information about unsatisfiable constraints. + * + * In the case of unsatisifiable constraints, the solver will drop + * unsatisfiable constraints of lowest priority. Information about these + * will be written to these lists after each iteration of constrained + * layout. + * + * param[out] unsatisfiableX A pointer to a UnsatisfiableConstraintInfos + * object that will be used to record + * unsatisfiable constraints in the x-dimension. + * param[out] unsatisfiableY A pointer to a UnsatisfiableConstraintInfos + * object that will be used to record + * unsatisfiable constraints in the y-dimension. + */ + void setUnsatisfiableConstraintInfo( + UnsatisfiableConstraintInfos *unsatisfiableX, + UnsatisfiableConstraintInfos *unsatisfiableY) + { + unsatisfiable.resize(2); + unsatisfiable[0]=unsatisfiableX; + unsatisfiable[1]=unsatisfiableY; + } + /** + * @brief Finds a feasible starting position for nodes that satisfies the + * given constraints. + * + * Starts with an initial position (x, y) for the nodes. This position + * is then iteratively updated with a greedy heuristic that tries adding + * additional constraints based on compound constraint priority to the + * satisfiable set, so as to satisfy as many of the placement constraints + * as possible. This includes automatically generated constraints for + * non-overlap and cluster containment. + * + * @param[in] xBorder Optional border width to add to left and right + * sides of rectangles. Defaults to 1. + * @param[in] yBorder Optional border width to add to top and bottom + * sides of rectangles. Defaults to 1. + * + * @note This method doesn't do force-directed layout. All forces are + * ignored and it merely satisfies the constraints with minimal + * movement to nodes. + */ + void makeFeasible(double xBorder=1, double yBorder=1); + + /** + * @brief A convenience method that can be called from Java to free + * the memory of nodes (Rectangles), CompoundConstraints, etc. + * + * This assumes that the ConstrainedFDLayout instance takes ownership + * of all the objects passed to it. + * + * This is useful because in SWIG we have problems with Java wrapper + * classes going out of scope and causing objects like Rectanges to + * sometimes be freed when the layout instance still needs them. For + * this reason we prevent the Java wrappers from deleting the internal + * C++ instances, and let them be cleaned up later via this method. + */ + void freeAssociatedObjects(void); + + //! @brief Generates an SVG file containing debug output and code that + //! can be used to regenerate the instance. + //! + //! This method can be called before or after run() or makeFeasible() + //! have been called. + //! + //! @param[in] filename A string indicating the filename (without + //! extension) for the output file. Defaults to + //! "libcola-debug.svg" if no filename is given. + //! + void outputInstanceToSVG(std::string filename = std::string()); + + /** + * @brief Specifies whether neighbour stress should be used. + * + * Under neighbour stress, only the terms representing neighbouring + * nodes contribute to the stress function. This can help to distribute + * nodes more evenly, eliminating long-range forces. + * + * Default value is false. + * + * @param[in] useNeighbourStress New boolean value for this option. + */ + void setUseNeighbourStress(bool useNeighbourStress); + + /** + * @brief Retrieve a copy of the "D matrix" computed by the computePathLengths + * method, linearised as a vector. + * + * This is especially useful for projects in SWIG target languages that want to + * do their own computations with stress. + * + * D is the required euclidean distances between pairs of nodes + * based on the shortest paths between them (using + * m_idealEdgeLength*eLengths[edge] as the edge length, if eLengths array + * is provided otherwise just m_idealEdgeLength). + * + * @return vector representing the D matrix. + */ + std::vector<double> readLinearD(void); + + /** + * @brief Retrieve a copy of the "G matrix" computed by the computePathLengths + * method, linearised as a vector. + * + * * This is especially useful for projects in SWIG target languages that want to + * do their own computations with stress. + * + * G is a matrix of unsigned ints such that G[u][v]= + * 0 if there are no forces required between u and v + * (for example, if u and v are in unconnected components) + * 1 if attractive forces are required between u and v + * (i.e. if u and v are immediately connected by an edge and there is + * no topology route between u and v (for which an attractive force + * is computed elsewhere)) + * 2 if no attractive force is required between u and v but there is + * a connected path between them. + * + * @return vector representing the G matrix. + */ + std::vector<unsigned> readLinearG(void); + + double computeStress() const; + +private: + unsigned n; // number of nodes + std::valarray<double> X, Y; + vpsc::Rectangles boundingBoxes; + double applyForcesAndConstraints(const vpsc::Dim dim,const double oldStress); + double computeStepSize(const SparseMatrix& H, const std::valarray<double>& g, + const std::valarray<double>& d) const; + void computeDescentVectorOnBothAxes(const bool xaxis, const bool yaxis, + double stress, std::valarray<double>& x0, std::valarray<double>& x1); + void moveTo(const vpsc::Dim dim, std::valarray<double>& target); + double applyDescentVector( + const std::valarray<double>& d, + const std::valarray<double>& oldCoords, + std::valarray<double> &coords, + const double oldStress, + double stepsize + /*,topology::TopologyConstraints *s=nullptr*/); + void computePathLengths( + const std::vector<Edge>& es, std::valarray<double> eLengths); + void generateNonOverlapAndClusterCompoundConstraints( + vpsc::Variables (&vs)[2]); + void handleResizes(const Resizes&); + void setPosition(std::valarray<double>& pos); + void moveBoundingBoxes(); + bool noForces(double, double, unsigned) const; + void computeForces(const vpsc::Dim dim, SparseMap &H, + std::valarray<double> &g); + void recGenerateClusterVariablesAndConstraints( + vpsc::Variables (&vars)[2], unsigned int& priority, + cola::NonOverlapConstraints *noc, Cluster *cluster, + cola::CompoundConstraints& idleConstraints); + std::vector<double> offsetDir(double minD); + + void computeNeighbours(std::vector<Edge> es); + std::vector<std::vector<unsigned> > neighbours; + std::vector<std::vector<double> > neighbourLengths; + TestConvergence *done; + bool using_default_done; // Whether we allocated a default TestConvergence object. + PreIteration* preIteration; + cola::CompoundConstraints ccs; + double** D; + unsigned short** G; + double minD; + PseudoRandom random; + + TopologyAddonInterface *topologyAddon; + std::vector<UnsatisfiableConstraintInfos*> unsatisfiable; + bool rungekutta; + DesiredPositions *desiredPositions; + cola::CompoundConstraints extraConstraints; + + RootCluster *clusterHierarchy; + double rectClusterBuffer; + double m_idealEdgeLength; + bool m_generateNonOverlapConstraints; + bool m_useNeighbourStress; + const std::valarray<double> m_edge_lengths; + + NonOverlapConstraintExemptions *m_nonoverlap_exemptions; + + friend class topology::ColaTopologyAddon; + friend class dialect::Graph; +}; + +struct ProjectionResult { + int errorLevel; + std::string unsatinfo; +}; + +/** + * @brief Attempt to do a projection onto a vector of cola CompoundConstraints. + * @param dim the dimension in which to perform the projection + * @param rs the rectangles representing the nodes + * @param ccs the constraints + * @param preventOverlaps boolean saying whether you want overlap prevention + * constraints to be automatically generated + * @param accept an integer indicating which types of infeasibilities you will accept. + * The default value of 0 means you accept no infeasibility. + * For other values, see the description of the "errorLevel" in the + * doctext for the solve function below. + * @param debugLevel see solve function below + * @note Rectangle positions are updated if and only if the error level is less + * than or equal to the accept level. + * @return a ProjectionResult indicating whether the projection was feasible or not. + * @sa solve + */ +ProjectionResult projectOntoCCs(vpsc::Dim dim, vpsc::Rectangles &rs, cola::CompoundConstraints ccs, + bool preventOverlaps, int accept=0, unsigned debugLevel=0); + +/** + * @brief Constructs a solver and attempts to solve the passed constraints on the passed vars. + * @param debugLevel: controls how much information comes back when the projection fails. See below. + * @return a ProjectionResult, containing: + * errorLevel: + * 0: all constraints were satisfiable. + * 1: some constraints were unsatisfiable, but they were all nonoverlap constraints. + * 2: some constraints were unsatisfiable which were /not/ nonoverlap constraints. + * unsatinfo: + * The amount of information reported depends on the debugLevel: + * 0: nothing reported (empty string) + * 1: description of the unsatisfied constraints + * 2: the info from level 1, plus a description of all "related" constraints (those sharing a variable). + * This is useful for understanding the conflicts. + */ +ProjectionResult solve(vpsc::Variables &vs, vpsc::Constraints &cs, vpsc::Rectangles &rs, + unsigned debugLevel=0); + + +ConstrainedMajorizationLayout* simpleCMLFactory( + vpsc::Rectangles& rs, + std::vector<Edge> const & es, + RootCluster* clusterHierarchy, + const double idealLength, + bool useNeighbourStress = false + ); + +/* + * find shortest path lengths from node s to all other nodes. + * @param s starting node + * @param n total number of nodes + * @param d n vector of path lengths + * @param es edge pairs + * @param eLengths edge weights + */ +void dijkstra(const unsigned s, const unsigned n, double* d, + const std::vector<cola::Edge>& es, + const std::valarray<double> & eLengths); + +#if 0 +void removeClusterOverlapFast(RootCluster& clusterHierarchy, vpsc::Rectangles& rs, Locks& locks); +#endif + +void setupVarsAndConstraints(unsigned n, const CompoundConstraints& ccs, + const vpsc::Dim dim, vpsc::Rectangles& boundingBoxes, + RootCluster *clusterHierarchy, + vpsc::Variables& vs, vpsc::Constraints& cs, + std::valarray<double> &coords); +void setVariableDesiredPositions(vpsc::Variables& vs, vpsc::Constraints& cs, + const DesiredPositionsInDim& des, std::valarray<double>& coords); + +} +#endif // COLA_H diff --git a/src/3rdparty/adaptagrams/libcola/cola_log.h b/src/3rdparty/adaptagrams/libcola/cola_log.h new file mode 100644 index 0000000..5909c93 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/cola_log.h @@ -0,0 +1,204 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +/* +Logging code from DJJ article: http://www.ddj.com/cpp/201804215. + +Title: Logging In C++ +Author: Petru Marginean +Keywords: OCT07 C++ +Description: Unpublished source code accompanying the article by Petru Marginean, in which he presents a C++ logging framework that is typesafe, thread-safe, and portable. + */ +#ifndef __COLA_LOG_H__ +#define __COLA_LOG_H__ + +#include <sstream> +#include <string> +#include <cstdio> +#include <iomanip> + +namespace cola { +inline std::string NowTime(); + +enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4}; + +template <typename T> +class Log +{ +public: + Log(); + virtual ~Log(); + std::ostringstream& Get(TLogLevel level = logINFO); +public: + static TLogLevel& ReportingLevel(); + static std::string ToString(TLogLevel level); + static TLogLevel FromString(const std::string& level); +protected: + std::ostringstream os; +private: + Log(const Log&); + Log& operator =(const Log&); +}; + +template <typename T> +Log<T>::Log() +{ +} + +template <typename T> +std::ostringstream& Log<T>::Get(TLogLevel level) +{ + os << "- " << NowTime(); + os << " " << ToString(level) << ": "; + os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t'); + return os; +} + +template <typename T> +Log<T>::~Log() +{ + os << std::endl; + T::Output(os.str()); +} + +template <typename T> +TLogLevel& Log<T>::ReportingLevel() +{ + static TLogLevel reportingLevel = cola::logDEBUG4; + return reportingLevel; +} + +template <typename T> +std::string Log<T>::ToString(TLogLevel level) +{ + static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"}; + return buffer[level]; +} + +template <typename T> +TLogLevel Log<T>::FromString(const std::string& level) +{ + if (level == "DEBUG4") + return logDEBUG4; + if (level == "DEBUG3") + return logDEBUG3; + if (level == "DEBUG2") + return logDEBUG2; + if (level == "DEBUG1") + return logDEBUG1; + if (level == "DEBUG") + return logDEBUG; + if (level == "INFO") + return logINFO; + if (level == "WARNING") + return logWARNING; + if (level == "ERROR") + return logERROR; + Log<T>().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default."; + return logINFO; +} + +class Output2FILE +{ +public: + static FILE*& Stream(); + static void Output(const std::string& msg); +}; + +inline FILE*& Output2FILE::Stream() +{ + static FILE* pStream = stderr; + return pStream; +} + +inline void Output2FILE::Output(const std::string& msg) +{ + FILE* pStream = Stream(); + if (!pStream) + return; + fprintf(pStream, "%s", msg.c_str()); + fflush(pStream); +} + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# if defined (BUILDING_FILELOG_DLL) +# define FILELOG_DECLSPEC __declspec (dllexport) +# elif defined (USING_FILELOG_DLL) +# define FILELOG_DECLSPEC __declspec (dllimport) +# else +# define FILELOG_DECLSPEC +# endif // BUILDING_DBSIMPLE_DLL +#else +# define FILELOG_DECLSPEC +#endif // _WIN32 + +class FILELOG_DECLSPEC FILELog : public Log<Output2FILE> {}; +//typedef Log<Output2FILE> FILELog; + +#ifndef FILELOG_MAX_LEVEL +#define FILELOG_MAX_LEVEL cola::logDEBUG4 +#endif + +#define FILE_LOG(level) \ + if (level > FILELOG_MAX_LEVEL) ;\ + else if (level > cola::FILELog::ReportingLevel() || !cola::Output2FILE::Stream()) ; \ + else cola::FILELog().Get(level) + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + +#include <windows.h> + +inline std::string NowTime() +{ + const int MAX_LEN = 200; + char buffer[MAX_LEN]; + if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, + "HH':'mm':'ss", buffer, MAX_LEN) == 0) + return "Error in NowTime()"; + + static DWORD first = GetTickCount(); + std::stringstream result; + result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)(GetTickCount() - first) % 1000); + return result.str(); +} + +#else + +#include <sys/time.h> + +inline std::string NowTime() +{ + char buffer[11]; + time_t t; + time(&t); + tm r; + strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r)); + struct timeval tv; + gettimeofday(&tv, 0); + std::stringstream result; + result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)tv.tv_usec / 1000); + return result.str(); +} + +#endif //WIN32 + +} // namespace cola + +#endif //__COLA_LOG_H__ diff --git a/src/3rdparty/adaptagrams/libcola/colafd.cpp b/src/3rdparty/adaptagrams/libcola/colafd.cpp new file mode 100644 index 0000000..8476f6b --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/colafd.cpp @@ -0,0 +1,1681 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2015 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer + * Michael Wybrow + * +*/ + +// cmath needs ::strcpy_s under MinGW so include cstring. +#include <cstring> + +#include <vector> +#include <cmath> +#include <limits> + +#include "libvpsc/solve_VPSC.h" +#include "libvpsc/variable.h" +#include "libvpsc/constraint.h" +#include "libvpsc/rectangle.h" +#include "libvpsc/exceptions.h" + +#include "libcola/commondefs.h" +#include "libcola/cola.h" +#include "libcola/shortest_paths.h" +#include "libcola/straightener.h" +#include "libcola/cc_clustercontainmentconstraints.h" +#include "libcola/cc_nonoverlapconstraints.h" + +#ifdef MAKEFEASIBLE_DEBUG + #include "libcola/output_svg.h" +#endif + +// Needs to come last since it will include windows.h on WIN32 and +// may mess up C++ std library include on GCC 4.4 +#include "libcola/cola_log.h" + +using namespace std; +using vpsc::Dim; +using vpsc::XDIM; +using vpsc::YDIM; +using vpsc::IncSolver; +using vpsc::Variable; +using vpsc::Variables; +using vpsc::Constraint; +using vpsc::Constraints; +using vpsc::Rectangle; +using vpsc::Rectangles; + +namespace cola { + +template <class T> +void delete_vector(vector<T*> &v) { + for_each(v.begin(),v.end(),delete_object()); + v.clear(); +} +Resizes PreIteration::__resizesNotUsed; +Locks PreIteration::__locksNotUsed; +inline double dotProd(valarray<double> x, valarray<double> y) { + COLA_ASSERT(x.size()==y.size()); + double dp=0; + for(unsigned i=0;i<x.size();i++) { + dp+=x[i]*y[i]; + } + return dp; +} +template <typename T> +void dumpSquareMatrix(unsigned n, T** L) { + printf("Matrix %dX%d\n{",n,n); + for(unsigned i=0;i<n;i++) { + printf("{"); + for(unsigned j=0;j<n;j++) { + std::cout<<L[i][j]; + char c=j==n-1?'}':','; + printf("%c",c); + } + char c=i==n-1?'}':','; + printf("%c\n",c); + } +} + +ConstrainedFDLayout::ConstrainedFDLayout(const vpsc::Rectangles& rs, + const std::vector< Edge >& es, const double idealLength, + const EdgeLengths& eLengths, + TestConvergence *doneTest, PreIteration* preIteration) + : n(rs.size()), + X(valarray<double>(n)), + Y(valarray<double>(n)), + done(doneTest), + using_default_done(false), + preIteration(preIteration), + topologyAddon(new TopologyAddonInterface()), + rungekutta(true), + desiredPositions(nullptr), + clusterHierarchy(nullptr), + rectClusterBuffer(0), + m_idealEdgeLength(idealLength), + m_generateNonOverlapConstraints(false), + m_useNeighbourStress(false), + m_edge_lengths(eLengths.data(), eLengths.size()), + m_nonoverlap_exemptions(new NonOverlapConstraintExemptions()) +{ + minD = DBL_MAX; + + if (done == nullptr) + { + done = new TestConvergence(); + using_default_done = true; + } + + computeNeighbours(es); + + //FILELog::ReportingLevel() = logDEBUG1; + FILELog::ReportingLevel() = logERROR; + boundingBoxes = rs; + done->reset(); + unsigned i=0; + for(vpsc::Rectangles::const_iterator ri=rs.begin();ri!=rs.end();++ri,++i) { + X[i]=(*ri)->getCentreX(); + Y[i]=(*ri)->getCentreY(); + FILE_LOG(logDEBUG) << *ri; + } + D=new double*[n]; + G=new unsigned short*[n]; + for(unsigned i=0;i<n;i++) { + D[i]=new double[n]; + G[i]=new unsigned short[n]; + } + + computePathLengths(es,m_edge_lengths); +} + +std::vector<double> ConstrainedFDLayout::readLinearD(void) +{ + std::vector<double> d; + d.resize(n*n); + for (unsigned i = 0; i < n; ++i) { + for (unsigned j = 0; j < n; ++j) { + d[n*i + j] = D[i][j]; + } + } + return d; +} + +std::vector<unsigned> ConstrainedFDLayout::readLinearG(void) +{ + std::vector<unsigned> g; + g.resize(n*n); + for (unsigned i = 0; i < n; ++i) { + for (unsigned j = 0; j < n; ++j) { + g[n*i + j] = G[i][j]; + } + } + return g; +} + +void ConstrainedFDLayout::computeNeighbours(vector<Edge> es) { + for (unsigned i = 0; i < n; ++i) { + neighbours.push_back(vector<unsigned>(n)); + } + for (vector<Edge>::iterator it = es.begin(); it!=es.end(); ++it) { + Edge e = *it; + unsigned s = e.first, t = e.second; + neighbours[s][t] = 1; + neighbours[t][s] = 1; + } +} + +void dijkstra(const unsigned s, const unsigned n, double* d, + const vector<Edge>& es, const std::valarray<double> & eLengths) +{ + shortest_paths::dijkstra(s,n,d,es,eLengths); +} + +void ConstrainedFDLayout::setConstraints(const cola::CompoundConstraints& ccs) +{ + this->ccs = ccs; +} + +void ConstrainedFDLayout::setAvoidNodeOverlaps(bool avoidOverlaps, + std::vector<std::vector<unsigned> > listOfNodeGroups) +{ + m_generateNonOverlapConstraints = avoidOverlaps; + m_nonoverlap_exemptions->addExemptGroupOfNodes(listOfNodeGroups); +} + +void ConstrainedFDLayout::setUseNeighbourStress(bool useNeighbourStress) +{ + m_useNeighbourStress = useNeighbourStress; +} + +void ConstrainedFDLayout::setDesiredPositions(DesiredPositions *desiredPositions) +{ + this->desiredPositions = desiredPositions; +} + + +/* + * Sets up the D and G matrices. D is the required euclidean distances + * between pairs of nodes based on the shortest paths between them (using + * m_idealEdgeLength*eLengths[edge] as the edge length, if eLengths array + * is provided otherwise just m_idealEdgeLength). G is a matrix of + * unsigned ints such that G[u][v]= + * 0 if there are no forces required between u and v + * (for example, if u and v are in unconnected components) + * 1 if attractive forces are required between u and v + * (i.e. if u and v are immediately connected by an edge and there is + * no topology route between u and v (for which an attractive force + * is computed elsewhere)) + * 2 if no attractive force is required between u and v but there is + * a connected path between them. + */ +void ConstrainedFDLayout::computePathLengths( + const vector<Edge>& es, std::valarray<double> eLengths) +{ + // Correct zero or negative entries in eLengths array. + for (size_t i = 0; i < eLengths.size(); ++i) + { + if (eLengths[i] <= 0) + { + fprintf(stderr, "Warning: ignoring non-positive length at index %d " + "in ideal edge length array.\n", (int) i); + eLengths[i] = 1; + } + } + + shortest_paths::johnsons(n,D,es,eLengths); + //dumpSquareMatrix<double>(n,D); + for(unsigned i=0;i<n;i++) { + for(unsigned j=0;j<n;j++) { + if(i==j) continue; + double& d=D[i][j]; + unsigned short& p=G[i][j]; + p=2; + if(d==DBL_MAX) { + // i and j are in disconnected subgraphs + p=0; + } else { + d*=m_idealEdgeLength; + } + + if ((d > 0) && (d < minD)) { + minD = d; + } + } + } + if (minD == DBL_MAX) minD = 1; + + for(vector<Edge>::const_iterator e=es.begin();e!=es.end();++e) { + unsigned u=e->first, v=e->second; + G[u][v]=G[v][u]=1; + } + topologyAddon->computePathLengths(G); + //dumpSquareMatrix<short>(n,G); +} + +typedef valarray<double> Position; +void getPosition(Position& X, Position& Y, Position& pos) { + unsigned n=X.size(); + COLA_ASSERT(Y.size()==n); + COLA_ASSERT(pos.size()==2*n); + for(unsigned i=0;i<n;++i) { + pos[i]=X[i]; + pos[i+n]=Y[i]; + } +} +/* + * moves all rectangles to the desired position while respecting + * constraints. + * @param pos target positions of both axes + */ +void ConstrainedFDLayout::setPosition(Position& pos) { + COLA_ASSERT(Y.size()==X.size()); + COLA_ASSERT(pos.size()==2*X.size()); + moveTo(vpsc::HORIZONTAL,pos); + moveTo(vpsc::VERTICAL,pos); +} +/* + * Layout is performed by minimizing the P-stress goal function iteratively. + * At each iteration taking a step in the steepest-descent direction. + * x0 is the current position, x1 is the x0 - descentvector. + */ +void ConstrainedFDLayout::computeDescentVectorOnBothAxes( + const bool xAxis, const bool yAxis, + double stress, Position& x0, Position& x1) { + setPosition(x0); + if(xAxis) { + applyForcesAndConstraints(vpsc::HORIZONTAL,stress); + } + if(yAxis) { + applyForcesAndConstraints(vpsc::VERTICAL,stress); + } + getPosition(X,Y,x1); +} + +/* + * run() implements the main layout loop, taking descent steps until + * stress is no-longer significantly reduced. + * done is a callback used to check stress but also to report updated + * positions. + */ +void ConstrainedFDLayout::run(const bool xAxis, const bool yAxis) +{ + // This generates constraints for non-overlap inside and outside + // of clusters. To assign correct variable indexes it requires + // that vs[] contains elements equal to the number of rectangles. + vpsc::Variables vs[2]; + vs[0].resize(n); + vs[1].resize(n); + generateNonOverlapAndClusterCompoundConstraints(vs); + + FILE_LOG(logDEBUG) << "ConstrainedFDLayout::run..."; + double stress=DBL_MAX; + do { + if(preIteration) { + if(!(*preIteration)()) { + break; + } + //printf("preIteration->changed=%d\n",preIteration->changed); + if(preIteration->changed) { + stress=DBL_MAX; + } + if(preIteration->resizes.size()>0) { + FILE_LOG(logDEBUG) << " Resize event!"; + handleResizes(preIteration->resizes); + } + } + unsigned N=2*n; + Position x0(N),x1(N); + getPosition(X,Y,x0); + if(rungekutta) { + Position a(N),b(N),c(N),d(N),ia(N),ib(N); + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,a); + ia=x0+(a-x0)/2.0; + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ia,b); + ib=x0+(b-x0)/2.0; + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ib,c); + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,c,d); + x1=a+2.0*b+2.0*c+d; + x1/=6.0; + } else { + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,x1); + } + setPosition(x1); + stress=computeStress(); + FILE_LOG(logDEBUG) << "stress="<<stress; + } while(!(*done)(stress,X,Y)); + for(unsigned i=0;i<n;i++) { + vpsc::Rectangle *r=boundingBoxes[i]; + FILE_LOG(logDEBUG) << *r; + } + FILE_LOG(logDEBUG) << "ConstrainedFDLayout::run done."; + + // Clear extra constraints. + for_each(extraConstraints.begin(), extraConstraints.end(), delete_object()); + extraConstraints.clear(); + + // Free extra variables used for cluster containment. + for (size_t dim = 0; dim < 2; ++dim) + { + for (size_t i = n; i < vs[dim].size(); ++i) + { + delete vs[dim][i]; + } + } +} + +/* + * Same as run, but only applies one iteration. This may be useful + * where it's too hard to implement a call-back (e.g. in java apps) + */ +void ConstrainedFDLayout::runOnce(const bool xAxis, const bool yAxis) { + if(n==0) return; + double stress=DBL_MAX; + unsigned N=2*n; + Position x0(N),x1(N); + getPosition(X,Y,x0); + if(rungekutta) { + Position a(N),b(N),c(N),d(N),ia(N),ib(N); + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,a); + ia=x0+(a-x0)/2.0; + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ia,b); + ib=x0+(b-x0)/2.0; + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ib,c); + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,c,d); + x1=a+2.0*b+2.0*c+d; + x1/=6.0; + } else { + computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,x1); + } +} + + +// Used for sorting the CompoundConstraints from lowest priority to highest. +static bool cmpCompoundConstraintPriority(const cola::CompoundConstraint *lhs, + const cola::CompoundConstraint *rhs) +{ + return lhs->priority() < rhs->priority(); +} + + +void ConstrainedFDLayout::recGenerateClusterVariablesAndConstraints( + vpsc::Variables (&vars)[2], unsigned int& priority, + cola::NonOverlapConstraints *noc, Cluster *cluster, + cola::CompoundConstraints& idleConstraints) +{ + for (std::vector<Cluster*>::iterator curr = cluster->clusters.begin(); + curr != cluster->clusters.end(); ++curr) + { + // For each of the child clusters, recursively call this function. + recGenerateClusterVariablesAndConstraints(vars, priority, + noc, *curr, idleConstraints); + } + + if ( (noc == nullptr) && (dynamic_cast<RootCluster *> (cluster) == nullptr) ) + { + double freeWeight = 0.00000000001; + // Then create left and right variables for the boundary of this + // cluster. + vpsc::Variable *variable = nullptr; + cluster->clusterVarId = vars[XDIM].size(); + COLA_ASSERT(vars[XDIM].size() == vars[YDIM].size()); + // Left: + variable = new vpsc::Variable(vars[XDIM].size(), + cluster->bounds.getMinX(), freeWeight); + vars[XDIM].push_back(variable); + // Right: + variable = new vpsc::Variable(vars[XDIM].size(), + cluster->bounds.getMaxX(), freeWeight); + vars[XDIM].push_back(variable); + // Bottom:: + variable = new vpsc::Variable(vars[YDIM].size(), + cluster->bounds.getMinY(), freeWeight); + vars[YDIM].push_back(variable); + // Top: + variable = new vpsc::Variable(vars[YDIM].size(), + cluster->bounds.getMaxY(), freeWeight); + vars[YDIM].push_back(variable); + + RectangularCluster *rc = dynamic_cast<RectangularCluster *> (cluster); + if (rc) + { + rc->generateFixedRectangleConstraints(idleConstraints, + boundingBoxes, vars); + } + + priority--; + cola::ClusterContainmentConstraints *ccc = + new cola::ClusterContainmentConstraints(cluster, priority, + boundingBoxes); + idleConstraints.push_back(ccc); + } + + if (noc) + { + // Enforce non-overlap between all the shapes and clusters at this + // level. + //printf("Cluster #%d non-overlap constraints - nodes %d clusters %d\n", + // (int) cluster->clusterVarId, (int) cluster->nodes.size(), + // (int) cluster->clusters.size()); + unsigned int group = cluster->clusterVarId; + // The set of clusters to put non-overlap constraints between is the + // child clusters of this cluster. We will also add any overlapping + // clusters (due to multiple inheritence) to this set. + std::set<Cluster *> expandedClusterSet(cluster->clusters.begin(), + cluster->clusters.end()); + for (std::set<unsigned>::iterator curr = cluster->nodes.begin(); + curr != cluster->nodes.end(); ++curr) + { + unsigned id = *curr; + + if (cluster->m_overlap_replacement_map.count(id) > 0) + { + // This shape is child of another cluster also, so replace + // this node with the other cluster for the purpose of + // non-overlap with other children of the current cluster. + expandedClusterSet.insert( + cluster->m_overlap_replacement_map[id]); + } + // Normal case: Add shape for generation of non-overlap + // constraints. + noc->addShape(id, boundingBoxes[id]->width() / 2, + boundingBoxes[id]->height() / 2, group); + } + for (std::set<Cluster*>::iterator curr = expandedClusterSet.begin(); + curr != expandedClusterSet.end(); ++curr) + { + Cluster *cluster = *curr; + RectangularCluster *rectCluster = + dynamic_cast<RectangularCluster *> (cluster); + if (rectCluster && rectCluster->clusterIsFromFixedRectangle()) + { + // Treat it like a shape for non-overlap. + unsigned id = rectCluster->rectangleIndex(); + noc->addShape(id, boundingBoxes[id]->width() / 2, + boundingBoxes[id]->height() / 2, group); + } + else + { + // Normal cluster. + noc->addCluster(cluster, group); + } + } + + // For the set of shapes that have been replaced due to multiple + // inheritance, still generate overlap constraints between them. + // (The group uses the ID of the right side variable of the cluster + // so it is not the same group as the cluster itself.) + for (std::set<unsigned>::iterator curr = + cluster->m_nodes_replaced_with_clusters.begin(); + curr != cluster->m_nodes_replaced_with_clusters.end(); ++curr) + { + unsigned id = *curr; + noc->addShape(id, boundingBoxes[id]->width() / 2, + boundingBoxes[id]->height() / 2, group + 1); + } + + } +} + +void ConstrainedFDLayout::generateNonOverlapAndClusterCompoundConstraints( + vpsc::Variables (&vs)[2]) +{ + if (clusterHierarchy && !clusterHierarchy->flat()) + { + // Add remaining nodes that aren't contained within any clusters + // as children of the root cluster. + std::vector<unsigned> nodesInClusterCounts(boundingBoxes.size(), 0); + clusterHierarchy->countContainedNodes(nodesInClusterCounts); + + for (unsigned int i = 0; i < nodesInClusterCounts.size(); ++i) + { + unsigned count = nodesInClusterCounts[i]; + if (!clusterHierarchy->allowsMultipleParents() && + count > 1) + { + fprintf(stderr, "Warning: node %u is contained in %d " + "clusters.\n", i, count); + } + + if (count == 0) + { + // Not present in hierarchy, so add to root cluster. + clusterHierarchy->nodes.insert(i); + } + } + + // Add non-overlap and containment constraints for all clusters + // and nodes. + unsigned int priority = PRIORITY_NONOVERLAP; + clusterHierarchy->computeBoundingRect(boundingBoxes); + + // Generate the containment constraints + recGenerateClusterVariablesAndConstraints(vs, priority, + nullptr, clusterHierarchy, extraConstraints); + + // Compute overlapping clusters. + clusterHierarchy->calculateClusterPathsToEachNode(boundingBoxes.size()); + + // Generate non-overlap constraints between all clusters and + // all contained nodes. + if (m_generateNonOverlapConstraints) + { + priority--; + cola::NonOverlapConstraints *noc = + new cola::NonOverlapConstraints(m_nonoverlap_exemptions, + priority); + noc->setClusterClusterExemptions( + clusterHierarchy->m_cluster_cluster_overlap_exceptions); + recGenerateClusterVariablesAndConstraints(vs, priority, + noc, clusterHierarchy, extraConstraints); + extraConstraints.push_back(noc); + } + } + else if (m_generateNonOverlapConstraints) + { + // Add standard non-overlap constraints between each pair of + // nodes. + cola::NonOverlapConstraints *noc = + new cola::NonOverlapConstraints(m_nonoverlap_exemptions); + for (unsigned int i = 0; i < boundingBoxes.size(); ++i) + { + noc->addShape(i, boundingBoxes[i]->width() / 2, + boundingBoxes[i]->height() / 2); + } + extraConstraints.push_back(noc); + } +} + +void ConstrainedFDLayout::makeFeasible(double xBorder, double yBorder) +{ + vpsc::Variables vs[2]; + vpsc::Constraints valid[2]; + + vpsc::Rectangle::setXBorder(xBorder); + vpsc::Rectangle::setYBorder(yBorder); + + // Populate all the variables for shapes. + for (unsigned int dim = 0; dim < 2; ++dim) + { + vs[dim] = vpsc::Variables(boundingBoxes.size()); + for (unsigned int i = 0; i < vs[dim].size(); ++i) + { + double pos = (dim == 0) ? + boundingBoxes[i]->getCentreX() : + boundingBoxes[i]->getCentreY(); + vs[dim][i] = new vpsc::Variable(i, pos, 1); + } + } + + vector<double> priorPos(boundingBoxes.size()); + + generateNonOverlapAndClusterCompoundConstraints(vs); + + // Make a copy of the compound constraints and sort them by priority. + cola::CompoundConstraints idleConstraints = ccs; + // Append extraConstraints to idleConstraints. + idleConstraints.insert(idleConstraints.end(), + extraConstraints.begin(), extraConstraints.end()); + + std::sort(idleConstraints.begin(), idleConstraints.end(), + cmpCompoundConstraintPriority); + + // Initialise extra variables for compound constraints. + for (unsigned int dim = 0; dim < 2; ++dim) + { + generateVariables(idleConstraints, (vpsc::Dim) dim, vs[dim]); + } + +#ifdef MAKEFEASIBLE_DEBUG + int iteration = 0; + vector<string> labels(boundingBoxes.size()); + for(unsigned i=0;i<boundingBoxes.size();++i) + { + stringstream ss; + ss << i; + labels[i]=ss.str(); + } +#endif + + // We can keep adding new constraints to the existing VPSC instances so + // long as everything is satisfiable. Only when it's not do we discard + // the existing VPSC instance for that dimension and create a new one. + vpsc::IncSolver *solver[2] = { nullptr }; + + // Main makeFeasible loop. + while (!idleConstraints.empty()) + { + // idleConstraints is sorted lowest to highest priority, so the + // highest priority constraint will be at the back of the vector. + cola::CompoundConstraint *cc = idleConstraints.back(); + idleConstraints.pop_back(); + +#ifdef MAKEFEASIBLE_DEBUG + { + // Debugging SVG time slice output. + std::vector<cola::Edge> es; + for (unsigned int i = 0; i < boundingBoxes.size(); ++i) + { + boundingBoxes[i]->moveCentreX(vs[0][i]->finalPosition); + boundingBoxes[i]->moveCentreY(vs[1][i]->finalPosition); + } + iteration++; + std::sstream filename; + filename << "out/file-" << std::setfill('0') << std::setw(5) << iteration << ".pdf"; + + OutputFile of(boundingBoxes,es,clusterHierarchy,filename.str().c_str(),true,false); + of.setLabels(labels); + of.generate(); + } +#endif + + cc->markAllSubConstraintsAsInactive(); + bool subConstraintSatisfiable = true; + + if (cc->shouldCombineSubConstraints()) + { + // We are processing a combined set of satisfiable constraints, + // such as for containment within cluster boundary variables, so + // we just add all the required constraints and solve in both + // the X and Y dimension once to set the cluster boundaries to + // meaningful values. + while (cc->subConstraintsRemaining()) + { + cola::SubConstraintAlternatives alternatives = + cc->getCurrSubConstraintAlternatives(vs); + // There should be no alternatives, just guaranteed + // satisfiable constraints. + COLA_ASSERT(alternatives.size() == 1); + vpsc::Dim& dim = alternatives.front().dim; + vpsc::Constraint& constraint = alternatives.front().constraint; + vpsc::Constraint *newConstraint = + new vpsc::Constraint(constraint); + valid[dim].push_back(newConstraint); + if (solver[dim]) + { + // If we have an existing valid solver instance, add the + // constraint to that. + solver[dim]->addConstraint(newConstraint); + } + cc->markCurrSubConstraintAsActive(subConstraintSatisfiable); + } + // Satisfy the constraints in each dimension. + for (size_t dim = 0; dim < 2; ++dim) + { + if (solver[dim] == nullptr) + { + // Create a new VPSC solver if necessary. + solver[dim] = new vpsc::IncSolver(vs[dim], valid[dim]); + } + solver[dim]->satisfy(); + } + continue; + } + + while (cc->subConstraintsRemaining()) + { + cola::SubConstraintAlternatives alternatives = + cc->getCurrSubConstraintAlternatives(vs); + alternatives.sort(); + + if (alternatives.empty()) + { + continue; + } + + while (!alternatives.empty()) + { + // Reset subConstraintSatisfiable for new solve. + subConstraintSatisfiable = true; + + vpsc::Dim& dim = alternatives.front().dim; + vpsc::Constraint& constraint = alternatives.front().constraint; + + // Store current values for variables. + for (unsigned int i = 0; i < priorPos.size(); ++i) + { + priorPos[i] = vs[dim][i]->finalPosition; + } + + // Some solving... + try + { + // Add the constraint from this alternative to the + // valid constraint set. + vpsc::Constraint *newConstraint = + new vpsc::Constraint(constraint); + valid[dim].push_back(newConstraint); + + //fprintf(stderr, ".%d %3d - ", dim, valid[dim].size()); + + // Try to satisfy this set of constraints.. + if (solver[dim] == nullptr) + { + // Create a new VPSC solver if necessary. + solver[dim] = new vpsc::IncSolver(vs[dim], valid[dim]); + } + else + { + // Or just add the constraint to the existing solver. + solver[dim]->addConstraint(newConstraint); + } + solver[dim]->satisfy(); + } + catch (char *str) + { + subConstraintSatisfiable = false; + + std::cerr << "++++ IN ERROR BLOCK" << std::endl; + std::cerr << str << std::endl; + for (vpsc::Rectangles::iterator r = boundingBoxes.begin(); + r != boundingBoxes.end(); ++r) + { + std::cerr << **r <<std::endl; + } + } + for (size_t i = 0; i < valid[dim].size(); ++i) + { + if (valid[dim][i]->unsatisfiable) + { + // It might have made one of the earlier added + // constraints unsatisfiable, so we mark that one + // as okay since we will be reverting the most + // recent one. + valid[dim][i]->unsatisfiable = false; + + subConstraintSatisfiable = false; + } + } + + if (!subConstraintSatisfiable) + { + // Since we had unsatisfiable constraints we must + // discard this solver instance. + delete solver[dim]; + solver[dim] = nullptr; + + // Restore previous values for variables. + for (unsigned int i = 0; i < priorPos.size(); ++i) + { + vs[dim][i]->finalPosition = priorPos[i]; + } + + // Delete the newly added (and unsatisfiable) + // constraint from the valid constraint set. + delete valid[dim].back(); + valid[dim].pop_back(); + } + else + { + // Satisfied, so don't need to consider other alternatives. + break; + } + // Move on to the next alternative. + alternatives.pop_front(); + } +#ifdef MAKEFEASIBLE_DEBUG + if (true || idleConstraints.size() == 0) + { + // Debugging SVG time slice output, but don't show this for + // constraints that promised satisfiable. + std::vector<cola::Edge> es; + for (unsigned int i = 0; i < boundingBoxes.size(); ++i) + { + boundingBoxes[i]->moveCentreX(vs[0][i]->finalPosition); + boundingBoxes[i]->moveCentreY(vs[1][i]->finalPosition); + } + iteration++; + std::sstream filename; + filename << "out/file-" << std::setfill('0') << std::setw(5) << iteration << ".pdf"; + + OutputFile of(boundingBoxes,es,clusterHierarchy,filename.str().c_str(), + true,false); + of.setLabels(labels); + of.generate(); + } +#endif + cc->markCurrSubConstraintAsActive(subConstraintSatisfiable); + } + } + + // Delete the persistent VPSC solver instances. + for (size_t dim = 0; dim < 2; ++dim) + { + if (solver[dim]) + { + delete solver[dim]; + solver[dim] = nullptr; + } + } + + // Write positions from solver variables back to Rectangles. + for (unsigned int i = 0; i < boundingBoxes.size(); ++i) + { + boundingBoxes[i]->moveCentreX(vs[0][i]->finalPosition); + boundingBoxes[i]->moveCentreY(vs[1][i]->finalPosition); + } + + vpsc::Rectangle::setXBorder(0); + vpsc::Rectangle::setYBorder(0); + + // Cleanup. + for (unsigned int dim = 0; dim < 2; ++dim) + { + for_each(valid[dim].begin(), valid[dim].end(), delete_object()); + for_each(vs[dim].begin(), vs[dim].end(), delete_object()); + } + + topologyAddon->makeFeasible(m_generateNonOverlapConstraints, + boundingBoxes, clusterHierarchy); + + // Update the X and Y vectors with the new shape positions. + for (unsigned int i = 0; i < boundingBoxes.size(); ++i) + { + X[i] = boundingBoxes[i]->getCentreX(); + Y[i] = boundingBoxes[i]->getCentreY(); + } + + // Clear extra constraints for cluster containment and non-overlap. + for_each(extraConstraints.begin(), extraConstraints.end(), delete_object()); + extraConstraints.clear(); +} + +ConstrainedFDLayout::~ConstrainedFDLayout() +{ + if (using_default_done) + { + delete done; + } + + for (unsigned i = 0; i < n; ++i) + { + delete [] G[i]; + delete [] D[i]; + } + delete [] G; + delete [] D; + delete topologyAddon; + delete m_nonoverlap_exemptions; +} + +void ConstrainedFDLayout::freeAssociatedObjects(void) +{ + // Free Rectangles + for_each(boundingBoxes.begin(), boundingBoxes.end(), delete_object()); + boundingBoxes.clear(); + + // Free compound constraints + std::list<CompoundConstraint *> freeList(ccs.begin(), ccs.end()); + freeList.sort(); + freeList.unique(); + if (freeList.size() != ccs.size()) + { + // The compound constraint list had repeated elements. + fprintf(stderr, "Warning: CompoundConstraints vector contained %d " + "duplicates.\n", (int) (ccs.size() - freeList.size())); + } + ccs.clear(); + for_each(freeList.begin(), freeList.end(), delete_object()); + + if (clusterHierarchy) + { + delete clusterHierarchy; + clusterHierarchy = nullptr; + } + + topologyAddon->freeAssociatedObjects(); +} + +void ConstrainedFDLayout::setTopology(TopologyAddonInterface *newTopology) +{ + COLA_ASSERT(topologyAddon); + delete topologyAddon; + topologyAddon = newTopology->clone(); +} + +TopologyAddonInterface *ConstrainedFDLayout::getTopology(void) +{ + return topologyAddon->clone(); +} + + +void setupVarsAndConstraints(unsigned n, const CompoundConstraints& ccs, + const vpsc::Dim dim, vpsc::Rectangles& boundingBoxes, + RootCluster *clusterHierarchy, + vpsc::Variables& vs, vpsc::Constraints& cs, + valarray<double> &coords) +{ + vs.resize(n); + for (unsigned i = 0; i < n; ++i) + { + vs[i] = new vpsc::Variable(i, coords[i]); + } + + if (clusterHierarchy && !clusterHierarchy->flat()) + { + // Create variables for clusters + clusterHierarchy->computeBoundingRect(boundingBoxes); + clusterHierarchy->createVars(dim, boundingBoxes, vs); + } + + for (CompoundConstraints::const_iterator c = ccs.begin(); + c != ccs.end(); ++c) + { + (*c)->generateVariables(dim, vs); + } + for (CompoundConstraints::const_iterator c = ccs.begin(); + c != ccs.end(); ++c) + { + (*c)->generateSeparationConstraints(dim, vs, cs, boundingBoxes); + } +} + + +static void setupExtraConstraints(const CompoundConstraints& ccs, + const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs, + vpsc::Rectangles& boundingBoxes) +{ + for (CompoundConstraints::const_iterator c = ccs.begin(); + c != ccs.end(); ++c) + { + (*c)->generateVariables(dim, vs); + } + for (CompoundConstraints::const_iterator c = ccs.begin(); + c != ccs.end(); ++c) + { + (*c)->generateSeparationConstraints(dim, vs, cs, boundingBoxes); + } +} + +void updateCompoundConstraints(const vpsc::Dim dim, + const CompoundConstraints& ccs) +{ + for (CompoundConstraints::const_iterator c = ccs.begin(); + c != ccs.end(); ++c) + { + (*c)->updatePosition(dim); + } +} +void project(vpsc::Variables& vs, vpsc::Constraints& cs, valarray<double>& coords) { + unsigned n=coords.size(); + vpsc::IncSolver s(vs,cs); + s.solve(); + for(unsigned i=0;i<n;++i) { + coords[i]=vs[i]->finalPosition; + } +} +void setVariableDesiredPositions(vpsc::Variables& vs, vpsc::Constraints& cs, + const DesiredPositionsInDim& des, valarray<double>& coords) +{ + COLA_UNUSED(cs); + + unsigned n=coords.size(); + COLA_ASSERT(vs.size()>=n); + for(unsigned i=0;i<n;++i) { + vpsc::Variable* v=vs[i]; + v->desiredPosition = coords[i]; + v->weight=1; + } + for (DesiredPositionsInDim::const_iterator d=des.begin(); + d!=des.end(); ++d) { + COLA_ASSERT(d->first<vs.size()); + vpsc::Variable* v=vs[d->first]; + v->desiredPosition = d->second; + v->weight=10000; + } +} +void checkUnsatisfiable(const vpsc::Constraints& cs, + UnsatisfiableConstraintInfos* unsatisfiable) { + for(vpsc::Constraints::const_iterator c=cs.begin();c!=cs.end();++c) { + if((*c)->unsatisfiable) { + UnsatisfiableConstraintInfo* i=new UnsatisfiableConstraintInfo(*c); + unsatisfiable->push_back(i); + } + } +} + +void ConstrainedFDLayout::handleResizes(const Resizes& resizeList) +{ + topologyAddon->handleResizes(resizeList, n, X, Y, ccs, boundingBoxes, + clusterHierarchy); +} + +/* + * move positions of nodes in specified axis while respecting constraints + * @param dim axis + * @param target array of desired positions (for both axes) + */ +void ConstrainedFDLayout::moveTo(const vpsc::Dim dim, Position& target) { + COLA_ASSERT(target.size()==2*n); + FILE_LOG(logDEBUG) << "ConstrainedFDLayout::moveTo(): dim="<<dim; + valarray<double> &coords = (dim==vpsc::HORIZONTAL)?X:Y; + vpsc::Variables vs; + vpsc::Constraints cs; + setupVarsAndConstraints(n, ccs, dim, boundingBoxes, + clusterHierarchy, vs, cs, coords); + DesiredPositionsInDim des; + if(preIteration) { + for(vector<Lock>::iterator l=preIteration->locks.begin(); + l!=preIteration->locks.end();l++) { + des.push_back(make_pair(l->getID(),l->pos(dim))); + FILE_LOG(logDEBUG1)<<"desi: v["<<l->getID()<<"]=("<<l->pos(vpsc::HORIZONTAL) + <<","<<l->pos(vpsc::VERTICAL)<<")"; + } + } + for(unsigned i=0, j=(dim==vpsc::HORIZONTAL?0:n);i<n;++i,++j) { + vpsc::Variable* v=vs[i]; + v->desiredPosition = target[j]; + } + setVariableDesiredPositions(vs,cs,des,coords); + if (topologyAddon->useTopologySolver()) + { + topologyAddon->moveTo(dim, vs, cs, coords, clusterHierarchy); + } else { + // Add non-overlap constraints, but not variables again. + setupExtraConstraints(extraConstraints, dim, vs, cs, boundingBoxes); + // Projection. + project(vs,cs,coords); + moveBoundingBoxes(); + } + updateCompoundConstraints(dim, ccs); + for_each(vs.begin(),vs.end(),delete_object()); + for_each(cs.begin(),cs.end(),delete_object()); +} +/* + * The following computes an unconstrained solution then uses Projection to + * make this solution feasible with respect to constraints by moving things as + * little as possible. If "meta-constraints" such as avoidOverlaps or edge + * straightening are required then dummy variables will be generated. + */ +double ConstrainedFDLayout::applyForcesAndConstraints(const vpsc::Dim dim, const double oldStress) { + FILE_LOG(logDEBUG) << "ConstrainedFDLayout::applyForcesAndConstraints(): dim="<<dim; + valarray<double> g(n); + valarray<double> &coords = (dim==vpsc::HORIZONTAL)?X:Y; + DesiredPositionsInDim des; + if(preIteration) { + for(vector<Lock>::iterator l=preIteration->locks.begin(); + l!=preIteration->locks.end();l++) { + des.push_back(make_pair(l->getID(),l->pos(dim))); + FILE_LOG(logDEBUG1)<<"desi: v["<<l->getID()<<"]=("<<l->pos(vpsc::HORIZONTAL) + <<","<<l->pos(vpsc::VERTICAL)<<")"; + } + } + vpsc::Variables vs; + vpsc::Constraints cs; + double stress; + setupVarsAndConstraints(n, ccs, dim, boundingBoxes, + clusterHierarchy, vs, cs, coords); + + if (topologyAddon->useTopologySolver()) + { + stress = topologyAddon->applyForcesAndConstraints(this, dim, g, vs, cs, + coords, des, oldStress); + } else { + // Add non-overlap constraints, but not variables again. + setupExtraConstraints(extraConstraints, dim, vs, cs, boundingBoxes); + // Projection. + SparseMap HMap(n); + computeForces(dim,HMap,g); + SparseMatrix H(HMap); + valarray<double> oldCoords=coords; + applyDescentVector(g,oldCoords,coords,oldStress,computeStepSize(H,g,g)); + setVariableDesiredPositions(vs,cs,des,coords); + project(vs,cs,coords); + valarray<double> d(n); + d=oldCoords-coords; + double stepsize=computeStepSize(H,g,d); + stepsize=max(0.,min(stepsize,1.)); + //printf(" dim=%d beta: ",dim); + stress = applyDescentVector(d,oldCoords,coords,oldStress,stepsize); + moveBoundingBoxes(); + } + updateCompoundConstraints(dim, ccs); + if(unsatisfiable.size()==2) { + checkUnsatisfiable(cs,unsatisfiable[dim]); + } + FILE_LOG(logDEBUG) << "ConstrainedFDLayout::applyForcesAndConstraints... done, stress="<<stress; + if (clusterHierarchy) + { + clusterHierarchy->computeVarRect(vs, dim); + clusterHierarchy->computeBoundingRect(boundingBoxes); + } + + for_each(vs.begin(),vs.end(),delete_object()); + for_each(cs.begin(),cs.end(),delete_object()); + return stress; +} +/* + * Attempts to set coords=oldCoords-stepsize*d. If this does not reduce + * the stress from oldStress then stepsize is halved. This is repeated + * until stepsize falls below a threshhold. + * @param d is a descent vector (a movement vector intended to reduce the + * stress) + * @param oldCoords are the previous position vector + * @param coords will hold the new position after applying d + * @param stepsize is a scalar multiple of the d to apply + */ +double ConstrainedFDLayout::applyDescentVector( + valarray<double> const &d, + valarray<double> const &oldCoords, + valarray<double> &coords, + const double oldStress, + double stepsize + ) +{ + COLA_UNUSED(oldStress); + + COLA_ASSERT(d.size()==oldCoords.size()); + COLA_ASSERT(d.size()==coords.size()); + while(fabs(stepsize)>0.00000000001) { + coords=oldCoords-stepsize*d; + double stress=computeStress(); + //printf(" applyDV: oldstress=%f, stress=%f, stepsize=%f\n", oldStress,stress,stepsize); + //if(oldStress>=stress) { + return stress; + //} + coords=oldCoords; + stepsize*=0.5; + } + return computeStress(); +} + + +// Computes X and Y offsets for nodes that are at the same position. +std::vector<double> ConstrainedFDLayout::offsetDir(double minD) +{ + std::vector<double> u(2); + double l = 0; + for (size_t i = 0; i < 2; ++i) + { + double x = u[i] = random.getNextBetween(0.01, 1) - 0.5; + l += x * x; + } + l = sqrt(l); + + for (size_t i = 0; i < 2; ++i) + { + u[i] *= (minD / l); + } + + return u; +} + + +/* + * Computes: + * - the matrix of second derivatives (the Hessian) H, used in + * calculating stepsize; and + * - the vector g, the negative gradient (steepest-descent) direction. + */ +void ConstrainedFDLayout::computeForces( + const vpsc::Dim dim, + SparseMap &H, + valarray<double> &g) { + if(n==1) return; + g=0; + // for each node: + for(unsigned u=0;u<n;u++) { + // Stress model + double Huu=0; + for(unsigned v=0;v<n;v++) { + if(u==v) continue; + if (m_useNeighbourStress && neighbours[u][v]!=1) continue; + + // The following loop randomly displaces nodes that are at identical positions + double rx=X[u]-X[v], ry=Y[u]-Y[v]; + double sd2 = rx*rx+ry*ry; + unsigned maxDisplaces = n; // avoid infinite loop in the case of numerical issues, such as huge values + + while (maxDisplaces--) + { + if ((sd2) > 1e-3) + { + break; + } + + std::vector<double> rd = offsetDir(minD); + X[v] += rd[0]; + Y[v] += rd[1]; + rx=X[u]-X[v], ry=Y[u]-Y[v]; + sd2 = rx*rx+ry*ry; + } + + unsigned short p = G[u][v]; + // no forces between disconnected parts of the graph + if(p==0) continue; + double l=sqrt(sd2); + double d=D[u][v]; + if(l>d && p>1) continue; // attractive forces not required + double d2=d*d; + /* force apart zero distances */ + if (l < 1e-30) { + l=0.1; + } + double dx=dim==vpsc::HORIZONTAL?rx:ry; + double dy=dim==vpsc::HORIZONTAL?ry:rx; + g[u]+=dx*(l-d)/(d2*l); + Huu-=H(u,v)=(d*dy*dy/(l*l*l)-1)/d2; + } + H(u,u)=Huu; + } + if(desiredPositions) { + for(DesiredPositions::const_iterator p=desiredPositions->begin(); + p!=desiredPositions->end();++p) { + unsigned i = p->id; + double d=(dim==vpsc::HORIZONTAL) + ?p->x-X[i]:p->y-Y[i]; + d*=p->weight; + g[i]-=d; + H(i,i)+=p->weight; + } + } +} +/* + * Returns the optimal step-size in the direction d, given gradient g and + * hessian H. + */ +double ConstrainedFDLayout::computeStepSize( + SparseMatrix const &H, + valarray<double> const &g, + valarray<double> const &d) const +{ + COLA_ASSERT(g.size()==d.size()); + COLA_ASSERT(g.size()==H.rowSize()); + // stepsize = g'd / (d' H d) + double numerator = dotProd(g,d); + valarray<double> Hd(d.size()); + H.rightMultiply(d,Hd); + double denominator = dotProd(d,Hd); + //COLA_ASSERT(numerator>=0); + //COLA_ASSERT(denominator>=0); + if(denominator==0) return 0; + return numerator/denominator; +} +/* + * Just computes the cost (Stress) at the current X,Y position + * used to test termination. + * This method will call preIteration if one is set. + */ +double ConstrainedFDLayout::computeStress() const { + FILE_LOG(logDEBUG)<<"ConstrainedFDLayout::computeStress()"; + double stress=0; + for(unsigned u=0;(u + 1)<n;u++) { + for(unsigned v=u+1;v<n;v++) { + if (m_useNeighbourStress && neighbours[u][v]!=1) continue; + unsigned short p=G[u][v]; + // no forces between disconnected parts of the graph + if(p==0) continue; + double rx=X[u]-X[v], ry=Y[u]-Y[v]; + double l=sqrt(rx*rx+ry*ry); + double d=D[u][v]; + if(l>d && p>1) continue; // no attractive forces required + double d2=d*d; + double rl=d-l; + double s=rl*rl/d2; + stress+=s; + FILE_LOG(logDEBUG2)<<"s("<<u<<","<<v<<")="<<s; + } + } + if(preIteration) { + if ((*preIteration)()) { + for(vector<Lock>::iterator l=preIteration->locks.begin(); + l!=preIteration->locks.end();l++) { + double dx=l->pos(vpsc::HORIZONTAL)-X[l->getID()], dy=l->pos(vpsc::VERTICAL)-Y[l->getID()]; + double s=10000*(dx*dx+dy*dy); + stress+=s; + FILE_LOG(logDEBUG2)<<"d("<<l->getID()<<")="<<s; + } + } + } + stress += topologyAddon->computeStress(); + if(desiredPositions) { + for(DesiredPositions::const_iterator p = desiredPositions->begin(); + p!=desiredPositions->end();++p) { + double dx = X[p->id] - p->x, dy = Y[p->id] - p->y; + stress+=0.5*p->weight*(dx*dx+dy*dy); + } + } + return stress; +} +void ConstrainedFDLayout::moveBoundingBoxes() { + for(unsigned i=0;i<n;i++) { + boundingBoxes[i]->moveCentre(X[i],Y[i]); + } +} + +static const double LIMIT = 100000000; + +static void reduceRange(double& val) +{ + val = std::min(val, LIMIT); + val = std::max(val, -LIMIT); +} + +void ConstrainedFDLayout::outputInstanceToSVG(std::string instanceName) +{ + std::string filename; + if (!instanceName.empty()) + { + filename = instanceName; + } + else + { + filename = "libcola-debug"; + } + filename += ".svg"; + FILE *fp = fopen(filename.c_str(), "w"); + + if (fp == nullptr) + { + return; + } + + + double minX = LIMIT; + double minY = LIMIT; + double maxX = -LIMIT; + double maxY = -LIMIT; + + // Find the bounds of the diagram. + for (size_t i = 0; i < boundingBoxes.size(); ++i) + { + double rMinX = boundingBoxes[i]->getMinX(); + double rMaxX = boundingBoxes[i]->getMaxX(); + double rMinY = boundingBoxes[i]->getMinY(); + double rMaxY = boundingBoxes[i]->getMaxY(); + + reduceRange(rMinX); + reduceRange(rMaxX); + reduceRange(rMinY); + reduceRange(rMaxY); + + if (rMinX > -LIMIT) + { + minX = std::min(minX, rMinX); + } + if (rMaxX < LIMIT) + { + maxX = std::max(maxX,rMaxX); + } + if (rMinY > -LIMIT) + { + minY = std::min(minY, rMinY); + } + if (rMaxY < LIMIT) + { + maxY = std::max(maxY, rMaxY); + } + } + + minX -= 50; + minY -= 50; + maxX += 50; + maxY += 50; + + fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + fprintf(fp, "<svg xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%%\" height=\"100%%\" viewBox=\"%g %g %g %g\">\n", minX, minY, maxX - minX, maxY - minY); + + // Output source code to generate this ConstrainedFDLayout instance. + fprintf(fp, "<!-- Source code to generate this instance:\n"); + fprintf(fp, "#include <vector>\n"); + fprintf(fp, "#include <utility>\n"); + fprintf(fp, "#include \"libcola/cola.h\"\n"); + fprintf(fp, "using namespace cola;\n"); + fprintf(fp, "int main(void) {\n"); + fprintf(fp, " CompoundConstraints ccs;\n"); + fprintf(fp, " std::vector<Edge> es;\n"); + fprintf(fp, " EdgeLengths eLengths;\n"); + fprintf(fp, " double defaultEdgeLength=%g;\n", m_idealEdgeLength); + fprintf(fp, " std::vector<vpsc::Rectangle*> rs;\n"); + fprintf(fp, " vpsc::Rectangle *rect = nullptr;\n\n"); + for (size_t i = 0; i < boundingBoxes.size(); ++i) + { + fprintf(fp, " rect = new vpsc::Rectangle(%g, %g, %g, %g);\n", + boundingBoxes[i]->getMinX(), boundingBoxes[i]->getMaxX(), + boundingBoxes[i]->getMinY(), boundingBoxes[i]->getMaxY()); + fprintf(fp, " rs.push_back(rect);\n\n"); + } + + for (size_t i = 0; i < n; ++i) + { + for (size_t j = i + 1; j < n; ++j) + { + if (G[i][j] == 1) + { + fprintf(fp, " es.push_back(std::make_pair(%lu, %lu));\n", i, j); + } + } + } + fprintf(fp, "\n"); + + if (m_edge_lengths.size() > 0) + { + fprintf(fp, " eLengths.resize(%d);\n", (int) m_edge_lengths.size()); + for (size_t i = 0; i < m_edge_lengths.size(); ++i) + { + fprintf(fp, " eLengths[%d] = %g;\n", (int) i, m_edge_lengths[i]); + } + fprintf(fp, "\n"); + } + + for (cola::CompoundConstraints::iterator c = ccs.begin(); + c != ccs.end(); ++c) + { + (*c)->printCreationCode(fp); + } + + fprintf(fp, " ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);\n"); + if (clusterHierarchy) + { + clusterHierarchy->printCreationCode(fp); + fprintf(fp, " alg.setClusterHierarchy(cluster%llu);\n", + (unsigned long long) clusterHierarchy); + } + fprintf(fp, " alg.setConstraints(ccs);\n"); + fprintf(fp, " alg.setAvoidNodeOverlaps(%s);\n", + (m_generateNonOverlapConstraints) ? "true" : "false"); + fprintf(fp, " alg.makeFeasible();\n"); + fprintf(fp, " alg.run();\n"); + fprintf(fp, " alg.freeAssociatedObjects();\n"); + fprintf(fp, " return 0;\n"); + fprintf(fp, "};\n"); + fprintf(fp, "-->\n"); + + if (clusterHierarchy) + { + clusterHierarchy->computeBoundingRect(boundingBoxes); + fprintf(fp, "<g inkscape:groupmode=\"layer\" " + "inkscape:label=\"Clusters\">\n"); + clusterHierarchy->outputToSVG(fp); + fprintf(fp, "</g>\n"); + } + + fprintf(fp, "<g inkscape:groupmode=\"layer\" " + "inkscape:label=\"Rects\">\n"); + for (size_t i = 0; i < boundingBoxes.size(); ++i) + { + double minX = boundingBoxes[i]->getMinX(); + double maxX = boundingBoxes[i]->getMaxX(); + double minY = boundingBoxes[i]->getMinY(); + double maxY = boundingBoxes[i]->getMaxY(); + + fprintf(fp, "<rect id=\"rect-%u\" x=\"%g\" y=\"%g\" width=\"%g\" " + "height=\"%g\" style=\"stroke-width: 1px; stroke: black; " + "fill: blue; fill-opacity: 0.3;\" />\n", + (unsigned) i, minX, minY, maxX - minX, maxY - minY); + } + fprintf(fp, "</g>\n"); + + fprintf(fp, "<g inkscape:groupmode=\"layer\" " + "inkscape:label=\"Edges\">\n"); + for (size_t i = 0; i < n; ++i) + { + for (size_t j = i + 1; j < n; ++j) + { + if (G[i][j] == 1) + { + fprintf(fp, "<path d=\"M %g %g L %g %g\" " + "style=\"stroke-width: 1px; stroke: black;\" />\n", + boundingBoxes[i]->getCentreX(), + boundingBoxes[i]->getCentreY(), + boundingBoxes[j]->getCentreX(), + boundingBoxes[j]->getCentreY()); + } + } + } + fprintf(fp, "</g>\n"); + + fprintf(fp, "</svg>\n"); + fclose(fp); +} + +ProjectionResult projectOntoCCs(Dim dim, Rectangles &rs, CompoundConstraints ccs, + bool preventOverlaps, int accept, unsigned debugLevel) +{ + size_t n = rs.size(); + // Set up nonoverlap constraints if desired. + NonOverlapConstraintExemptions *nocexemps = nullptr; + NonOverlapConstraints *noc = nullptr; + if (preventOverlaps) { + nocexemps = new NonOverlapConstraintExemptions(); + noc = new NonOverlapConstraints(nocexemps); + for (size_t i = 0; i < n; ++i) { + noc->addShape(i, rs[i]->width()/2.0, rs[i]->height()/2.0); + } + ccs.push_back(noc); + } + // Set up vars and constraints. + Variables vs; + Constraints cs; + vs.resize(n); + for (size_t i = 0; i < n; ++i) { + vs[i] = new Variable(i, rs[i]->getCentreD(dim)); + } + for (CompoundConstraints::iterator it=ccs.begin(); it!=ccs.end(); ++it) { + CompoundConstraint *cc = *it; + cc->generateVariables(dim, vs); + cc->generateSeparationConstraints(dim, vs, cs, rs); + } + // Solve, if possible. + ProjectionResult result = solve(vs, cs, rs, debugLevel); + // If good enough, accept positions. + if (result.errorLevel <= accept) { + for (size_t i = 0; i < n; ++i) { + rs[i]->moveCentreD(dim, vs[i]->finalPosition); + } + } + // Clean up + for (Variables::iterator it=vs.begin(); it!=vs.end(); ++it) delete *it; + for (Constraints::iterator it=cs.begin(); it!=cs.end(); ++it) delete *it; + delete noc; + delete nocexemps; + // Return + return result; +} + +ProjectionResult solve(Variables &vs, Constraints &cs, Rectangles &rs, unsigned debugLevel) +{ + int result = 0; + IncSolver solv(vs,cs); + try { + solv.solve(); + } catch (vpsc::UnsatisfiedConstraint uc) { + } + for (Constraints::iterator it=cs.begin(); it!=cs.end(); it++) { + Constraint *c = *it; + if (c->unsatisfiable) { + CompoundConstraint *cc = (CompoundConstraint*)(c->creator); + if (cc->toString() == "NonOverlapConstraints()") { + result = 1; + } else { + result = 2; + break; + } + } + } + std::string unsatinfo; + if (debugLevel>0) { + std::set<Variable*> varsInvolved; + unsatinfo += "===================================================\n"; + unsatinfo += "UNSATISFIED CONSTRAINTS:\n"; + char buf [1000]; + for (Constraints::iterator it=cs.begin(); it!=cs.end(); it++) { + Constraint *c = *it; + if (c->unsatisfiable) { + varsInvolved.insert(c->left); + varsInvolved.insert(c->right); + sprintf(buf, "v_%d + %f", c->left->id, c->gap); + unsatinfo += buf; + unsatinfo += c->equality ? " == " : " <= "; + sprintf(buf, "v_%d\n", c->right->id); + unsatinfo += buf; + if ((unsigned) c->left->id < rs.size()) { + Rectangle *r = rs[c->left->id]; + sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->left->id, + r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY()); + unsatinfo += buf; + } + if ((unsigned) c->right->id < rs.size()) { + Rectangle *r = rs[c->right->id]; + sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->right->id, + r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY()); + unsatinfo += buf; + } + CompoundConstraint *cc = (CompoundConstraint*)(c->creator); + unsatinfo += " Creator: " + cc->toString() + "\n"; + } + } + if (debugLevel>1) { + unsatinfo += "--------------------------------------------------\n"; + unsatinfo += "RELATED CONSTRAINTS:\n"; + std::set<Variable*>::iterator lit, rit, eit = varsInvolved.end(); + for (Constraints::iterator it=cs.begin(); it!=cs.end(); it++) { + Constraint *c = *it; + lit = varsInvolved.find(c->left); + rit = varsInvolved.find(c->right); + if (lit != eit || rit != eit) { + sprintf(buf, "v_%d + %f", c->left->id, c->gap); + unsatinfo += buf; + unsatinfo += c->equality ? " == " : " <= "; + sprintf(buf, "v_%d\n", c->right->id); + unsatinfo += buf; + if ((unsigned) c->left->id < rs.size()) { + Rectangle *r = rs[c->left->id]; + sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->left->id, + r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY()); + unsatinfo += buf; + } + if ((unsigned) c->right->id < rs.size()) { + Rectangle *r = rs[c->right->id]; + sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->right->id, + r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY()); + unsatinfo += buf; + } + CompoundConstraint *cc = (CompoundConstraint*)(c->creator); + unsatinfo += " Creator: " + cc->toString() + "\n"; + } + } + } + } + ProjectionResult pr; + pr.errorLevel = result; + pr.unsatinfo = unsatinfo; + return pr; +} + +} // namespace cola diff --git a/src/3rdparty/adaptagrams/libcola/commondefs.h b/src/3rdparty/adaptagrams/libcola/commondefs.h new file mode 100644 index 0000000..6d56f62 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/commondefs.h @@ -0,0 +1,98 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef _COMMONDEFS_H +#define _COMMONDEFS_H + +/* Notes to compilation using MSVC. + + Compiler options: + /Zc:forScope +*/ +#if defined(_MSC_VER) +// Microsoft Visual C++ (MS VC) specific code goes here +#include <float.h> +#include <malloc.h> // Contains _alloca +#endif + +#include "libvpsc/assertions.h" +#include <valarray> + +namespace cola { + +/* + * resolve overlaps: + * None: not at all + * Horizontal: only horizontally + * Both: resolve in either Horizontal or Vertical direction + * depending on which leads to less displacement + */ +enum NonOverlapConstraintsMode { None, Horizontal, Both }; + +class FixedList { +public: + FixedList(const unsigned n) : array(std::valarray<bool>(n)),allFixed(false) + { + array=false; + } + void set(const unsigned i, const bool value=true) { + COLA_ASSERT(i<array.size()); + array[i]=value; + } + bool check(const unsigned i) const { + if(allFixed||i>=array.size()) { + return false; + } + return array[i]; + } + void unsetAll() { + array=false; + } + void fixAll(bool val) { + allFixed=val; + } +private: + std::valarray<bool> array; + bool allFixed; +}; + +/* + * templated delete functor for use in for_each loop over vector + */ +struct delete_object +{ + template <typename T> + void operator()(T *ptr){ delete ptr;} +}; +/* + * Sum over the results of calling operation for each member in the + * iterator. Handier than std::accumulate because we can use with + * mem_fun to pass in a getter method. + */ +template <class InputIterator, class T, class Operation > +T sum_over(InputIterator beg, InputIterator end, T init, Operation op) +{ + for ( ; beg != end; ++beg) + init = init + op(*beg); + return init; +} +} // namespace cola + +#endif diff --git a/src/3rdparty/adaptagrams/libcola/compound_constraints.cpp b/src/3rdparty/adaptagrams/libcola/compound_constraints.cpp new file mode 100644 index 0000000..af9fa3e --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/compound_constraints.cpp @@ -0,0 +1,1671 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer + * Michael Wybrow +*/ + +#include <algorithm> +#include <climits> +#include <sstream> + +#include <libvpsc/variable.h> +#include <libvpsc/constraint.h> +#include <libvpsc/assertions.h> + +#include "libcola/cola.h" +#include "libcola/compound_constraints.h" +#include "libcola/exceptions.h" + +using std::vector; +using vpsc::XDIM; +using vpsc::YDIM; + +namespace cola { + +void SubConstraintInfo::updateVarIDsWithMapping( + const VariableIDMap& idMap, bool forward) +{ + varIndex = idMap.mappingForVariable(varIndex, forward); +} + +//----------------------------------------------------------------------------- +// BoundaryConstraint code +//----------------------------------------------------------------------------- + +class Offset : public SubConstraintInfo +{ + public: + Offset(unsigned ind, double offset) : + SubConstraintInfo(ind), + distOffset(offset) + { + } + double distOffset; +}; + + +BoundaryConstraint::BoundaryConstraint(const vpsc::Dim dim) + : CompoundConstraint(dim), + position(0), + variable(nullptr) +{ +} + + +void BoundaryConstraint::updatePosition(const vpsc::Dim dim) +{ + if (dim == _primaryDim) + { + position = variable->finalPosition; + } +} + + +void BoundaryConstraint::addShape(const unsigned int index, + const double offset) +{ + _subConstraintInfo.push_back(new Offset(index, offset)); +} + + +void BoundaryConstraint::printCreationCode(FILE *fp) const +{ + fprintf(fp, " BoundaryConstraint *boundary%llu = " + "new BoundaryConstraint(vpsc::%cDIM);\n", + (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y'); + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + Offset *info = static_cast<Offset *> (*o); + fprintf(fp, " boundary%llu->addShape(%u, %g);\n", + (unsigned long long) this, info->varIndex, info->distOffset); + } + fprintf(fp, " ccs.push_back(boundary%llu);\n\n", + (unsigned long long) this); +} + + +std::string BoundaryConstraint::toString(void) const +{ + std::ostringstream stream; + stream << "BoundaryConstraint("; + stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y'); + stream << "): {"; + bool first = true; + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + Offset *info = static_cast<Offset *> (*o); + if (!first) + { + stream << ", "; + } + stream << "(" << "rect: " << info->varIndex << ", offset: " << info->distOffset << ")"; + first = false; + } + stream << "}"; + return stream.str(); +} + + +void BoundaryConstraint::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + if (dim == _primaryDim) + { + // Just one variable is generated, associated with the position + // of the boundary. This variable can float freely. + variable = new vpsc::Variable(vars.size(), position, freeWeight); + vars.push_back(variable); + } +} + + +void BoundaryConstraint::generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& cs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(bbs); + if (dim == _primaryDim) + { + COLA_ASSERT(variable != nullptr); + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + Offset *info = static_cast<Offset *> (*o); + assertValidVariableIndex(vars, info->varIndex); + vpsc::Constraint *constraint = nullptr; + if (info->distOffset < 0) + { + // Constrain the objects with negative offsets to be + // to the left of the boundary. + constraint = new vpsc::Constraint(vars[info->varIndex], + variable, -info->distOffset); + } + else + { + // Constrain the objects with positive offsets to be + // to the right of the boundary. + constraint = new vpsc::Constraint(variable, + vars[info->varIndex], info->distOffset); + } + constraint->creator = this; + cs.push_back(constraint); + } + } +} + + +SubConstraintAlternatives +BoundaryConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + SubConstraintAlternatives alternatives; + + Offset *info = static_cast<Offset *> + (_subConstraintInfo[_currSubConstraintIndex]); + + assertValidVariableIndex(vs[_primaryDim], info->varIndex); + if (info->distOffset < 0) + { + // Constrain the objects with negative offsets to be + // to the left of the boundary. + vpsc::Constraint constraint = vpsc::Constraint( + vs[_primaryDim][info->varIndex], variable, -info->distOffset); + alternatives.push_back(SubConstraint(_primaryDim, constraint)); + } + else + { + // Constrain the objects with positive offsets to be + // to the right of the boundary. + vpsc::Constraint constraint = vpsc::Constraint( + variable, vs[_primaryDim][info->varIndex], info->distOffset); + alternatives.push_back(SubConstraint(_primaryDim, constraint)); + } + + //fprintf(stderr, "===== BOUNDARYLINE ALTERNATIVES -======\n"); + return alternatives; +} + + + +//----------------------------------------------------------------------------- +// AlignmentConstraint code +//----------------------------------------------------------------------------- + +AlignmentConstraint::AlignmentConstraint(const vpsc::Dim dim, double position) + : CompoundConstraint(dim), + indicator(nullptr), + variable(nullptr), + _position(position), + _isFixed(false) +{ +} + + +void AlignmentConstraint::addShape(const unsigned int index, + const double offset) +{ + _subConstraintInfo.push_back(new Offset(index, offset)); +} + + +void AlignmentConstraint::updatePosition(const vpsc::Dim dim) +{ + if (dim == _primaryDim) + { + _position = variable->finalPosition; + } +} + + +void AlignmentConstraint::fixPos(double pos) +{ + _position = pos; + _isFixed = true; +} + + +void AlignmentConstraint::unfixPos() +{ + _isFixed = false; +} + + +double AlignmentConstraint::position(void) const +{ + return _position; +} + +bool AlignmentConstraint::isFixed(void) const +{ + return _isFixed; +} + +void AlignmentConstraint::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + if (dim == _primaryDim) + { + // Variable representing the position of a guideline. + variable = new vpsc::Variable(vars.size(), _position, freeWeight); + if (_isFixed) + { + variable->fixedDesiredPosition = true; + variable->weight = 100000; + } + vars.push_back(variable); + } +} + + +void AlignmentConstraint::generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& cs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(bbs); + if (dim == _primaryDim) + { + COLA_ASSERT(variable != nullptr); + // Constrain each object to be offset from the guideline by + // some exact amount. + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + Offset *info = static_cast<Offset *> (*o); + assertValidVariableIndex(vars, info->varIndex); + vpsc::Constraint *constraint = new vpsc::Constraint( + variable, vars[info->varIndex], info->distOffset, true); + constraint->creator = this; + cs.push_back(constraint); + } + } +} + +void AlignmentConstraint::updateShapeOffsetsForDifferentCentres( + const std::vector<double>& offsets, bool forward) +{ + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + Offset *info = static_cast<Offset *> (*o); + if (offsets[info->varIndex] == 0) + { + continue; + } + + if (forward) + { + info->distOffset -= offsets[info->varIndex]; + } + else + { + info->distOffset += offsets[info->varIndex]; + } + } +} + +void AlignmentConstraint::printCreationCode(FILE *fp) const +{ + fprintf(fp, " AlignmentConstraint *alignment%llu = " + "new AlignmentConstraint(vpsc::%cDIM, %g);\n", + (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y', + _position); + if (_isFixed) + { + fprintf(fp, " alignment%llu->fixPos(%g);\n", + (unsigned long long) this, _position); + } + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + Offset *info = static_cast<Offset *> (*o); + fprintf(fp, " alignment%llu->addShape(%u, %g);\n", + (unsigned long long) this, info->varIndex, info->distOffset); + } + fprintf(fp, " ccs.push_back(alignment%llu);\n\n", + (unsigned long long) this); +} + + +std::string AlignmentConstraint::toString(void) const +{ + std::ostringstream stream; + stream << "AlignmentConstraint("; + stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y'); + stream << ", pos: " << _position; + if (_isFixed) + { + stream << ", fixed: true"; + } +#if 0 + // TODO: buggy. Not the right value. + if (variable) + { + stream << ", varInd: " << variable->id; + } +#endif + stream << "): {"; + bool first = true; + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + Offset *info = static_cast<Offset *> (*o); + if (!first) + { + stream << ", "; + } + stream << "(" << "rect: " << info->varIndex << ", offset: " << info->distOffset << ")"; + first = false; + } + stream << "}"; + return stream.str(); +} + + +SubConstraintAlternatives +AlignmentConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + SubConstraintAlternatives alternatives; + + Offset *info = static_cast<Offset *> + (_subConstraintInfo[_currSubConstraintIndex]); + + assertValidVariableIndex(vs[_primaryDim], info->varIndex); + vpsc::Constraint constraint(variable, vs[_primaryDim][info->varIndex], + info->distOffset, true); + alternatives.push_back(SubConstraint(_primaryDim, constraint)); + + //fprintf(stderr, "===== ALIGN ALTERNATIVES -======\n"); + return alternatives; +} + + +//----------------------------------------------------------------------------- +// SeparationConstraint code +//----------------------------------------------------------------------------- + + +class VarIndexPair : public SubConstraintInfo +{ + public: + VarIndexPair(unsigned ind1, unsigned ind2) + : SubConstraintInfo(ind1), + lConstraint(nullptr), + rConstraint(nullptr), + varIndex2(ind2) + { + } + VarIndexPair(AlignmentConstraint *l, AlignmentConstraint *r) + : SubConstraintInfo(0), + lConstraint(l), + rConstraint(r), + varIndex2(0) + { + } + unsigned indexL(void) const + { + return (lConstraint) ? + (unsigned) lConstraint->variable->id : varIndex; + } + unsigned indexR(void) const + { + return (rConstraint) ? + (unsigned) rConstraint->variable->id : varIndex2; + } + void updateVarIDsWithMapping(const VariableIDMap& idMap, bool forward) + { + varIndex = idMap.mappingForVariable(varIndex, forward); + varIndex2 = idMap.mappingForVariable(varIndex2, forward); + } + + AlignmentConstraint *lConstraint; + AlignmentConstraint *rConstraint; + unsigned varIndex2; +}; + + +SeparationConstraint::SeparationConstraint(const vpsc::Dim dim, + unsigned l, unsigned r, double g, bool equality) + : CompoundConstraint(dim), + gap(g), + equality(equality), + vpscConstraint(nullptr) +{ + _subConstraintInfo.push_back(new VarIndexPair(l, r)); +} + + +SeparationConstraint::SeparationConstraint(const vpsc::Dim dim, + AlignmentConstraint *l, AlignmentConstraint *r, double g, + bool equality) + : CompoundConstraint(dim), + gap(g), + equality(equality) +{ + COLA_ASSERT(l); + COLA_ASSERT(r); + + _subConstraintInfo.push_back(new VarIndexPair(l, r)); +} + + +void SeparationConstraint::printCreationCode(FILE *fp) const +{ + assert(_subConstraintInfo.size() == 1); + VarIndexPair *varIndexPair = (VarIndexPair *) _subConstraintInfo.front(); + if (varIndexPair->lConstraint && varIndexPair->rConstraint) + { + fprintf(fp, " SeparationConstraint *separation%llu = " + "new SeparationConstraint(vpsc::%cDIM, alignment%llu, " + "alignment%llu, %g, %s);\n", + (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y', + (unsigned long long) varIndexPair->lConstraint, + (unsigned long long) varIndexPair->rConstraint, gap, + (equality) ? "true" : "false"); + } + else + { + fprintf(fp, " SeparationConstraint *separation%llu = " + "new SeparationConstraint(vpsc::%cDIM, %u, %u, %g, %s);\n", + (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y', + varIndexPair->indexL(), varIndexPair->indexR(), gap, + (equality) ? "true" : "false"); + } + fprintf(fp, " ccs.push_back(separation%llu);\n\n", + (unsigned long long) this); +} + + +std::string SeparationConstraint::toString(void) const +{ + std::ostringstream stream; + stream << "SeparationConstraint("; + stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y'); + stream << ", sep: " << gap; + stream << ", equality: " << ((equality) ? "true" : "false"); + stream << "): {"; + VarIndexPair *varIndexPair = (VarIndexPair *) _subConstraintInfo.front(); + if (varIndexPair->lConstraint && varIndexPair->rConstraint) + { + stream << "(alignment: " << varIndexPair->indexL() << "), "; + stream << "(alignment: " << varIndexPair->indexR() << "), "; + } + else + { + stream << "(rect: " << varIndexPair->indexL() << "), "; + stream << "(rect: " << varIndexPair->indexR() << "), "; + } + stream << "}"; + return stream.str(); +} + + +void SeparationConstraint::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + COLA_UNUSED(dim); + COLA_UNUSED(vars); + + // No additional variables are required! +} + + +SubConstraintAlternatives +SeparationConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + SubConstraintAlternatives alternatives; + + VarIndexPair *info = static_cast<VarIndexPair *> + (_subConstraintInfo[_currSubConstraintIndex]); + + assertValidVariableIndex(vs[_primaryDim], info->indexL()); + assertValidVariableIndex(vs[_primaryDim], info->indexR()); + vpsc::Constraint constraint(vs[_primaryDim][info->indexL()], + vs[_primaryDim][info->indexR()], gap, equality); + alternatives.push_back(SubConstraint(_primaryDim, constraint)); + + //fprintf(stderr, "===== SEPARATION ALTERNATIVES -======\n"); + return alternatives; +} + + +void SeparationConstraint::generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vs, vpsc::Constraints& cs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(bbs); + if (dim == _primaryDim) + { + VarIndexPair *info = + static_cast<VarIndexPair *> (_subConstraintInfo.front()); + + unsigned left = info->indexL(); + unsigned right = info->indexR(); + assertValidVariableIndex(vs, left); + assertValidVariableIndex(vs, right); + vpscConstraint = + new vpsc::Constraint(vs[left], vs[right], gap, equality); + vpscConstraint->creator = this; + cs.push_back(vpscConstraint); + } +} + + +unsigned SeparationConstraint::left(void) const +{ + VarIndexPair *info = + static_cast<VarIndexPair *> (_subConstraintInfo.front()); + + return info->indexL(); +} + + +unsigned SeparationConstraint::right(void) const +{ + VarIndexPair *info = + static_cast<VarIndexPair *> (_subConstraintInfo.front()); + + return info->indexR(); +} + + +void SeparationConstraint::setSeparation(double gap) +{ + this->gap = gap; + if (vpscConstraint != nullptr) + { + vpscConstraint->gap = gap; + } +} + + +//----------------------------------------------------------------------------- +// OrthogonalEdgeConstraint code +//----------------------------------------------------------------------------- + +OrthogonalEdgeConstraint::OrthogonalEdgeConstraint(const vpsc::Dim dim, + unsigned l, unsigned r) + : CompoundConstraint(dim), + left(l), + right(r), + vpscConstraint(nullptr) +{ +} + + +void OrthogonalEdgeConstraint::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + COLA_UNUSED(dim); + COLA_UNUSED(vars); + + // No additional variables are required! +} + + +void OrthogonalEdgeConstraint::printCreationCode(FILE *fp) const +{ + fprintf(fp, " /* OrthogonalEdgeConstraint *orthogonal%llu = nullptr; */\n\n", + (unsigned long long) this); +} + + +std::string OrthogonalEdgeConstraint::toString(void) const +{ + std::ostringstream stream; + stream << "OrthogonalEdgeConstraint()"; + return stream.str(); +} + + + +SubConstraintAlternatives +OrthogonalEdgeConstraint::getCurrSubConstraintAlternatives( + vpsc::Variables vs[]) +{ + COLA_UNUSED(vs); + + // XXX: What to do here? + _currSubConstraintIndex = _subConstraintInfo.size(); + return SubConstraintAlternatives(); +} + + +void OrthogonalEdgeConstraint::generateSeparationConstraints( + const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(bbs); + if (dim == _primaryDim) + { + assertValidVariableIndex(vs, left); + assertValidVariableIndex(vs, right); + vpscConstraint = new vpsc::Constraint(vs[left], vs[right], 0, true); + vpscConstraint->creator = this; + cs.push_back(vpscConstraint); + } +} + + +void OrthogonalEdgeConstraint::generateTopologyConstraints(const vpsc::Dim k, + const vpsc::Rectangles& rs, vector<vpsc::Variable*> const & vars, + vector<vpsc::Constraint*> & cs) +{ + assertValidVariableIndex(vars, left); + assertValidVariableIndex(vars, right); + double lBound, rBound, pos; + if (k == vpsc::HORIZONTAL) + { + lBound = rs[left]->getCentreY(); + rBound = rs[right]->getCentreY(); + pos = rs[left]->getCentreX(); + } + else + { + lBound = rs[left]->getCentreX(); + rBound = rs[right]->getCentreX(); + pos = rs[left]->getCentreY(); + } + double minBound = std::min(lBound, rBound); + double maxBound = std::max(lBound, rBound); + for (unsigned i = 0; i < rs.size(); ++i) + { + if (i==left || i==right) continue; + vpsc::Rectangle *r = rs[i]; + if (r->allowOverlap()) continue; + double l, rMin, rMax, rCentre; + rectBounds(k, r, rMin, rMax, rCentre, l); + if ( ((rMin >= minBound) && (rMin <= maxBound)) || + ((rMax >= minBound) && (rMax <= maxBound))) + { + double g = l / 2; + if (rCentre < pos) + { + cs.push_back(new vpsc::Constraint(vars[i], vars[left], g)); + } + else + { + cs.push_back(new vpsc::Constraint(vars[left], vars[i], g)); + } + } + } +} + + +void OrthogonalEdgeConstraint::rectBounds(const vpsc::Dim k, + vpsc::Rectangle const *r, double& cmin, double& cmax, + double& centre, double & l) const +{ + if (k == vpsc::HORIZONTAL) + { + cmin = r->getMinY(); + cmax = r->getMaxY(); + centre = r->getCentreX(); + l = r->width(); + } + else + { + cmin = r->getMinX(); + cmax = r->getMaxX(); + centre = r->getCentreY(); + l = r->height(); + } +} + + +//----------------------------------------------------------------------------- +// MultiSeparationConstraint code +//----------------------------------------------------------------------------- + +class AlignmentPair : public SubConstraintInfo +{ + public: + AlignmentPair(AlignmentConstraint *ac1, AlignmentConstraint *ac2) + : SubConstraintInfo(0), + alignment1(ac1), + alignment2(ac2) + { + } + AlignmentConstraint *alignment1; + AlignmentConstraint *alignment2; +}; + + +MultiSeparationConstraint::MultiSeparationConstraint(const vpsc::Dim dim, + double minSep, bool equality) + : CompoundConstraint(dim), + indicator(nullptr), + sep(minSep), + equality(equality) +{ +} + + +void MultiSeparationConstraint::addAlignmentPair(AlignmentConstraint *ac1, + AlignmentConstraint *ac2) +{ + _subConstraintInfo.push_back(new AlignmentPair(ac1, ac2)); +} + + +void MultiSeparationConstraint::printCreationCode(FILE *fp) const +{ + fprintf(fp, " MultiSeparationConstraint *multiSep%llu = " + "new MultiSeparationConstraint(vpsc::%cDIM, %g, %s);\n", + (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y', sep, + (equality) ? "true" : "false"); + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + AlignmentPair *pair = static_cast<AlignmentPair *> (*o); + fprintf(fp, " multiSep%llu->addAlignmentPair(" + "alignment%llu, alignment%llu);\n", + (unsigned long long) this, + (unsigned long long) pair->alignment1, + (unsigned long long) pair->alignment2); + } + fprintf(fp, " ccs.push_back(multiSep%llu);\n\n", + (unsigned long long) this); +} + + +std::string MultiSeparationConstraint::toString(void) const +{ + std::ostringstream stream; + stream << "MultiSeparationConstraint("; + stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y'); + stream << ", sep: " << sep; + stream << ", equality: " << ((equality) ? "true" : "false"); + stream << "): {"; + bool first = true; + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + if (!first) + { + stream << ", "; + } + AlignmentPair *pair = static_cast<AlignmentPair *> (*o); + stream << "(alignment: " << pair->alignment1->variable->id + << ", alignment: " << pair->alignment2->variable->id << ")"; + first = false; + } + stream << "}"; + return stream.str(); +} + + +void MultiSeparationConstraint::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + COLA_UNUSED(dim); + COLA_UNUSED(vars); + + // No additional variables are required! +} + + +SubConstraintAlternatives +MultiSeparationConstraint::getCurrSubConstraintAlternatives( + vpsc::Variables vs[]) +{ + COLA_UNUSED(vs); + + SubConstraintAlternatives alternatives; + + AlignmentPair *info = static_cast<AlignmentPair *> + (_subConstraintInfo[_currSubConstraintIndex]); + + AlignmentConstraint *c1 = info->alignment1; + AlignmentConstraint *c2 = info->alignment2; + if (!c1->variable || !c2->variable) + { + throw InvalidConstraint(this); + } + vpsc::Constraint constraint(c1->variable, c2->variable, sep, equality); + alternatives.push_back(SubConstraint(_primaryDim, constraint)); + + //fprintf(stderr, "===== MULTI SEPARATION ALTERNATIVES -======\n"); + return alternatives; +} + + +void MultiSeparationConstraint::setSeparation(double sep) +{ + this->sep = sep; +} + + +void MultiSeparationConstraint::generateSeparationConstraints( + const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& gcs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(vs); + COLA_UNUSED(bbs); + + if (dim == _primaryDim) + { + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + AlignmentPair *info = static_cast<AlignmentPair *> (*o); + AlignmentConstraint *c1 = info->alignment1; + AlignmentConstraint *c2 = info->alignment2; + if (!c1->variable || !c2->variable) + { + throw InvalidConstraint(this); + } + vpsc::Constraint *c = new vpsc::Constraint( + c1->variable, c2->variable, sep, equality); + c->creator = this; + gcs.push_back(c); + cs.push_back(c); + } + } +} + + +//----------------------------------------------------------------------------- +// DistributionConstraint code +//----------------------------------------------------------------------------- + +DistributionConstraint::DistributionConstraint(const vpsc::Dim dim) + : CompoundConstraint(dim), + indicator(nullptr) +{ +} + + +void DistributionConstraint::addAlignmentPair(AlignmentConstraint *ac1, + AlignmentConstraint *ac2) +{ + _subConstraintInfo.push_back(new AlignmentPair(ac1, ac2)); +} + + +void DistributionConstraint::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + COLA_UNUSED(dim); + COLA_UNUSED(vars); + + // No additional variables are required! +} + + +void DistributionConstraint::setSeparation(double sep) +{ + this->sep = sep; +} + + +void DistributionConstraint::printCreationCode(FILE *fp) const +{ + fprintf(fp, " DistributionConstraint *distribution%llu = " + "new DistributionConstraint(vpsc::%cDIM);\n", + (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y'); + fprintf(fp, " distribution%llu->setSeparation(%g);\n", + (unsigned long long) this, sep); + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + AlignmentPair *pair = static_cast<AlignmentPair *> (*o); + fprintf(fp, " distribution%llu->addAlignmentPair(" + "alignment%llu, alignment%llu);\n", + (unsigned long long) this, + (unsigned long long) pair->alignment1, + (unsigned long long) pair->alignment2); + } + fprintf(fp, " ccs.push_back(distribution%llu);\n\n", + (unsigned long long) this); +} + + +std::string DistributionConstraint::toString(void) const +{ + std::ostringstream stream; + stream << "DistributionConstraint("; + stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y'); + stream << ", sep: " << sep; + stream << "): {"; + bool first = true; + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + if (!first) + { + stream << ", "; + } + AlignmentPair *pair = static_cast<AlignmentPair *> (*o); + stream << "(alignment: " << pair->alignment1->variable->id + << ", alignment: " << pair->alignment2->variable->id << ")"; + first = false; + } + stream << "}"; + return stream.str(); +} + + +SubConstraintAlternatives +DistributionConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + COLA_UNUSED(vs); + + SubConstraintAlternatives alternatives; + + AlignmentPair *info = static_cast<AlignmentPair *> + (_subConstraintInfo[_currSubConstraintIndex]); + AlignmentConstraint *c1 = info->alignment1; + AlignmentConstraint *c2 = info->alignment2; + if (!c1->variable || !c2->variable) + { + throw InvalidConstraint(this); + } + vpsc::Constraint constraint(c1->variable, c2->variable, sep, true); + alternatives.push_back(SubConstraint(_primaryDim, constraint)); + + //fprintf(stderr, "===== DISTRIBUTION ALTERNATIVES -======\n"); + return alternatives; +} + + +void DistributionConstraint::generateSeparationConstraints( + const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& gcs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(vars); + COLA_UNUSED(bbs); + + if (dim == _primaryDim) + { + cs.clear(); + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + AlignmentPair *info = static_cast<AlignmentPair *> (*o); + AlignmentConstraint *c1 = info->alignment1; + AlignmentConstraint *c2 = info->alignment2; + if (!c1->variable || !c2->variable) + { + throw InvalidConstraint(this); + } + vpsc::Constraint *c=new vpsc::Constraint( + c1->variable, c2->variable, sep, true); + c->creator = this; + gcs.push_back(c); + cs.push_back(c); +#if 0 + // The following was an experiment to allow variable distributions + // solved by optimisation rather than satisfying constraints + if(isVariable) { + // set second derivatives of: + // (u + g - v)^2 = g^2 + 2gu + u^2 - 2gv - 2uv + v^2 + (*Q)[make_pair(c1->variable->id,c1->variable->id)]+=w; + (*Q)[make_pair(c2->variable->id,c2->variable->id)]+=w; + (*Q)[make_pair(variable->id,variable->id)]+=w; + (*Q)[make_pair(c1->variable->id,c2->variable->id)]-=w; + (*Q)[make_pair(c2->variable->id,c1->variable->id)]-=w; + (*Q)[make_pair(c1->variable->id,variable->id)]+=w; + (*Q)[make_pair(variable->id,c1->variable->id)]+=w; + (*Q)[make_pair(c2->variable->id,variable->id)]-=w; + (*Q)[make_pair(variable->id,c2->variable->id)]-=w; + } +#endif + } + } +} + + +//----------------------------------------------------------------------------- +// FixedRelativeConstraint code +//----------------------------------------------------------------------------- + +class RelativeOffset : public SubConstraintInfo +{ + public: + RelativeOffset(unsigned indL, unsigned indR, vpsc::Dim dim, + double offset) + : SubConstraintInfo(indL), + varIndex2(indR), + dim(dim), + distOffset(offset) + { + } + void updateVarIDsWithMapping(const VariableIDMap& idMap, bool forward) + { + varIndex = idMap.mappingForVariable(varIndex, forward); + varIndex2 = idMap.mappingForVariable(varIndex2, forward); + } + + unsigned varIndex2; + vpsc::Dim dim; + double distOffset; +}; + + +FixedRelativeConstraint::FixedRelativeConstraint(const vpsc::Rectangles& rs, + std::vector<unsigned> shapeIds, const bool fixedPosition) + : CompoundConstraint(vpsc::XDIM), + m_fixed_position(fixedPosition), + m_shape_vars(shapeIds) +{ + _combineSubConstraints = true; + + // Make sure that m_shape_vars doesn't contain duplicates. + std::sort(m_shape_vars.begin(), m_shape_vars.end()); + std::vector<unsigned>::iterator last = + std::unique(m_shape_vars.begin(), m_shape_vars.end()); + m_shape_vars.erase(last, m_shape_vars.end()); + + unsigned firstId = UINT_MAX; + COLA_ASSERT(m_shape_vars.size() >= 2); + for (std::vector<unsigned>::iterator it = m_shape_vars.begin(); + it != m_shape_vars.end(); ++it) + { + COLA_ASSERT(*it < rs.size()); + + if (it == m_shape_vars.begin()) + { + firstId = *it; + } + else + { + unsigned thisId = *it; + _subConstraintInfo.push_back( + new RelativeOffset(firstId, thisId, vpsc::XDIM, + rs[thisId]->getCentreX() - rs[firstId]->getCentreX())); + _subConstraintInfo.push_back( + new RelativeOffset(firstId, thisId, vpsc::YDIM, + rs[thisId]->getCentreY() - rs[firstId]->getCentreY())); + } + } +} + +void FixedRelativeConstraint::updateVarIDsWithMapping( + const VariableIDMap& idMap, bool forward) +{ + CompoundConstraint::updateVarIDsWithMapping(idMap, forward); + + // We need to map variables in m_shape_vars too, + // since this is used in generateVariables(). + for (size_t i = 0; i < m_shape_vars.size(); ++i) + { + m_shape_vars[i] = idMap.mappingForVariable(m_shape_vars[i], forward); + } +} + + + +void FixedRelativeConstraint::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + COLA_UNUSED(dim); + COLA_UNUSED(vars); + + // No additional variables are required! + + // Fix shape positions if required. + if (m_fixed_position) + { + for (std::vector<unsigned>::iterator it = m_shape_vars.begin(); + it != m_shape_vars.end(); ++it) + { + vars[*it]->fixedDesiredPosition = true; + vars[*it]->weight = 100000; + } + } +} + + +void FixedRelativeConstraint::printCreationCode(FILE *fp) const +{ + fprintf(fp, " std::vector<unsigned> fixedRelativeSet%llu;\n", + (unsigned long long) this); + for (std::vector<unsigned>::const_iterator it = m_shape_vars.begin(); + it != m_shape_vars.end(); ++it) + { + fprintf(fp, " fixedRelativeSet%llu.push_back(%u);\n", + (unsigned long long) this, *it); + } + fprintf(fp, " FixedRelativeConstraint *fixedRelative%llu = " + "new FixedRelativeConstraint(rs, fixedRelativeSet%llu, %s);\n", + (unsigned long long) this, (unsigned long long) this, + (m_fixed_position) ? "true" : "false"); + fprintf(fp, " ccs.push_back(fixedRelative%llu);\n\n", + (unsigned long long) this); +} + + +std::string FixedRelativeConstraint::toString(void) const +{ + std::ostringstream stream; + stream << "FixedRelativeConstraint("; + stream << "fixedPos: " << ((m_fixed_position) ? "true" : "false"); + stream << "): {"; + bool first = true; + for (std::vector<unsigned>::const_iterator it = m_shape_vars.begin(); + it != m_shape_vars.end(); ++it) + { + if (!first) + { + stream << ", "; + } + stream << "(rect: " << *it << ")"; + first = false; + } + stream << "}"; + return stream.str(); +} + + +SubConstraintAlternatives +FixedRelativeConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + COLA_UNUSED(vs); + + SubConstraintAlternatives alternatives; + + RelativeOffset *offset = static_cast<RelativeOffset *> + (_subConstraintInfo[_currSubConstraintIndex]); + + vpsc::Dim dim = offset->dim; + vpsc::Constraint constraint(vs[dim][offset->varIndex], + vs[dim][offset->varIndex2], offset->distOffset, true); + alternatives.push_back(SubConstraint(dim, constraint)); + + //fprintf(stderr, "===== FixedRelativeConstraint ALTERNATIVES -======\n"); + return alternatives; +} + + +void FixedRelativeConstraint::generateSeparationConstraints( + const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& ccs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(vars); + COLA_UNUSED(bbs); + + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + RelativeOffset *offset = static_cast<RelativeOffset *> (*o); + if (dim != offset->dim) + { + continue; + } + + assertValidVariableIndex(vars, offset->varIndex); + assertValidVariableIndex(vars, offset->varIndex2); + vpsc::Constraint *c = + new vpsc::Constraint(vars[offset->varIndex], + vars[offset->varIndex2], offset->distOffset, true); + c->creator = this; + ccs.push_back(c); + } +} + + +//----------------------------------------------------------------------------- +// PageBoundaryConstraint code +//----------------------------------------------------------------------------- + +class PageBoundaryShapeOffsets : public SubConstraintInfo +{ + public: + PageBoundaryShapeOffsets(unsigned ind, double xOffset, double yOffset) : + SubConstraintInfo(ind) + { + halfDim[0] = xOffset; + halfDim[1] = yOffset; + } + double halfDim[2]; // half width and height values; +}; + + +PageBoundaryConstraints::PageBoundaryConstraints(double xLow, double xHigh, + double yLow, double yHigh, double weight) + : CompoundConstraint(vpsc::HORIZONTAL) +{ + COLA_ASSERT(xLow < xHigh); + COLA_ASSERT(yLow < yHigh); + + leftMargin[vpsc::XDIM] = xLow; + rightMargin[vpsc::XDIM] = xHigh; + leftMargin[vpsc::YDIM] = yLow; + rightMargin[vpsc::YDIM] = yHigh; + + for (unsigned i = 0; i < 2; ++i) + { + actualLeftMargin[i] = leftMargin[i]; + actualRightMargin[i] = rightMargin[i]; + leftWeight[i] = weight; + rightWeight[i] = weight; + vl[i] = nullptr; + vr[i] = nullptr; + } +} + + +void PageBoundaryConstraints::addShape(unsigned id, double halfW, double halfH) +{ + _subConstraintInfo.push_back(new PageBoundaryShapeOffsets(id, halfW, halfH)); +} + + +void PageBoundaryConstraints::printCreationCode(FILE *fp) const +{ + fprintf(fp, " PageBoundaryConstraints *pageBoundary%llu = " + "new PageBoundaryConstraints(%g, %g, %g, %g, %g);\n", + (unsigned long long) this, leftMargin[vpsc::XDIM], + rightMargin[vpsc::XDIM], leftMargin[vpsc::YDIM], + rightMargin[vpsc::YDIM], leftWeight[0]); + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + PageBoundaryShapeOffsets *offsets = + static_cast<PageBoundaryShapeOffsets *> (*o); + fprintf(fp, " pageBoundary%llu->addShape(%u, %g, %g);\n", + (unsigned long long) this, offsets->varIndex, + offsets->halfDim[XDIM], offsets->halfDim[YDIM]); + } + fprintf(fp, " ccs.push_back(pageBoundary%llu);\n\n", + (unsigned long long) this); +} + + +std::string PageBoundaryConstraints::toString(void) const +{ + std::ostringstream stream; + stream << "PageBoundaryConstraints("; + stream << "xLow: " << leftMargin[vpsc::XDIM]; + stream << ", xHigh: " << rightMargin[vpsc::XDIM]; + stream << ", yLow: " << leftMargin[vpsc::YDIM]; + stream << ", yHigh: " << rightMargin[vpsc::YDIM]; + stream << ", weight: " << leftWeight[0]; + stream << "): {"; + bool first = true; + for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + if (!first) + { + stream << ", "; + } + PageBoundaryShapeOffsets *offsets = + static_cast<PageBoundaryShapeOffsets *> (*o); + stream << "(rect: " << offsets->varIndex; + stream << ", halfWidth: " << offsets->halfDim[XDIM]; + stream << ", halfHeight: " << offsets->halfDim[YDIM]; + stream <<")"; + first = false; + } + stream << "}"; + return stream.str(); +} + +SubConstraintAlternatives +PageBoundaryConstraints::getCurrSubConstraintAlternatives(vpsc::Variables vs[]) +{ + COLA_UNUSED(vs); + + // Page boundary constraints do not need to be evaluated at the + // time of makeFeasible, so we return an empty list here. + _currSubConstraintIndex = _subConstraintInfo.size(); + return SubConstraintAlternatives(); +} + + +void PageBoundaryConstraints::updatePosition(const vpsc::Dim dim) +{ + if (vl[dim]) + { + actualLeftMargin[dim] = vl[dim]->finalPosition; + } + + if (vr[dim]) + { + actualRightMargin[dim] = vr[dim]->finalPosition; + } +} + + +double PageBoundaryConstraints::getActualLeftMargin(const vpsc::Dim dim) +{ + return actualLeftMargin[dim]; +} + + +double PageBoundaryConstraints::getActualRightMargin(const vpsc::Dim dim) +{ + return actualRightMargin[dim]; +} + + +void PageBoundaryConstraints::generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) +{ + // create 2 dummy vars, based on the dimension we are in + if (leftWeight[dim]) + { + vars.push_back(vl[dim] = new vpsc::Variable(vars.size(), + leftMargin[dim], leftWeight[dim])); + vl[dim]->fixedDesiredPosition = true; + } + + if (rightWeight[dim]) + { + vars.push_back(vr[dim] = new vpsc::Variable(vars.size(), + rightMargin[dim], rightWeight[dim])); + vr[dim]->fixedDesiredPosition = true; + } +} + + +void PageBoundaryConstraints::generateSeparationConstraints( + const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs, + vpsc::Rectangles& bbs) +{ + COLA_UNUSED(bbs); + // For each of the "real" variables, create a constraint that puts + // that var between our two new dummy vars, depending on the dimension. + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + PageBoundaryShapeOffsets *info = + static_cast<PageBoundaryShapeOffsets *> (*o); + assertValidVariableIndex(vs, info->varIndex); + if (vl[dim]) + { + vpsc::Constraint *constraint = new vpsc::Constraint(vl[dim], + vs[info->varIndex], info->halfDim[dim]); + constraint->creator = this; + cs.push_back(constraint); + } + + if (vr[dim]) + { + vpsc::Constraint *constraint = new vpsc::Constraint( + vs[info->varIndex], vr[dim], info->halfDim[dim]); + constraint->creator = this; + cs.push_back(constraint); + } + } +} + + +//----------------------------------------------------------------------------- +// Support code +//----------------------------------------------------------------------------- + + +struct GenerateVariables +{ + GenerateVariables(const vpsc::Dim dim, vpsc::Variables& vars) + : dim(dim), + vars(vars) + { + } + void operator() (CompoundConstraint *c) + { + c->generateVariables(dim, vars); + } + + const vpsc::Dim dim; + vpsc::Variables& vars; +}; + + +struct GenerateSeparationConstraints +{ + GenerateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables& vars, + vpsc::Constraints& cs, vpsc::Rectangles& bbs) + : dim(dim), + vars(vars), + cs(cs), + bbs(bbs) + { + } + void operator() (CompoundConstraint *c) + { + c->generateSeparationConstraints(dim, vars, cs, bbs); + } + const vpsc::Dim dim; + vpsc::Variables& vars; + vpsc::Constraints& cs; + vpsc::Rectangles& bbs; +}; + + +void generateVariablesAndConstraints(CompoundConstraints& ccs, + const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& cs, + vpsc::Rectangles& bbs) +{ + for_each(ccs.begin(), ccs.end(), + GenerateVariables(dim, vars)); + for_each(ccs.begin(), ccs.end(), + GenerateSeparationConstraints(dim, vars, cs, bbs)); +} + + +void generateVariables(CompoundConstraints& ccs, const vpsc::Dim dim, + vpsc::Variables& vars) +{ + for_each(ccs.begin(), ccs.end(), + GenerateVariables(dim, vars)); +} + + +CompoundConstraint::CompoundConstraint(vpsc::Dim primaryDim, + unsigned int priority) : + _primaryDim(primaryDim), + _secondaryDim((vpsc::Dim) ((primaryDim + 1) % 2)), + _priority(priority), + _combineSubConstraints(false), + _currSubConstraintIndex(0) +{ +} + + +CompoundConstraint::~CompoundConstraint() +{ + // Free memory from the subConstraintInfo list. + for_each(_subConstraintInfo.begin(), _subConstraintInfo.end(), delete_object()); + _subConstraintInfo.clear(); +} + + +vpsc::Dim CompoundConstraint::dimension(void) const +{ + return _primaryDim; +} + + +unsigned int CompoundConstraint::priority(void) const +{ + return _priority; +} + + +void CompoundConstraint::printCreationCode(FILE *fp) const +{ + COLA_UNUSED(fp); + + // Do nothing. Subclasses can implement this. +} + +void CompoundConstraint::updateVarIDsWithMapping(const VariableIDMap& idMap, + bool forward) +{ + for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin(); + o != _subConstraintInfo.end(); ++o) + { + (*o)->updateVarIDsWithMapping(idMap, forward); + } +} + + +std::list<unsigned> CompoundConstraint::subConstraintObjIndexes(void) const +{ + std::list<unsigned> idList; + for (size_t i = 0; i < _subConstraintInfo.size(); ++i) + { + idList.push_back(_subConstraintInfo[i]->varIndex); + } + return idList; +} + + +bool CompoundConstraint::subConstraintsRemaining(void) const +{ + return _currSubConstraintIndex < _subConstraintInfo.size(); +} + + +void CompoundConstraint::markAllSubConstraintsAsInactive(void) +{ + for (size_t i = 0; i < _subConstraintInfo.size(); ++i) + { + _subConstraintInfo[i]->satisfied = false; + } + _currSubConstraintIndex = 0; +} + + +void CompoundConstraint::markCurrSubConstraintAsActive(const bool satisfiable) +{ + _subConstraintInfo[_currSubConstraintIndex]->satisfied = satisfiable; + + _currSubConstraintIndex++; +} + + +void CompoundConstraint::assertValidVariableIndex(const vpsc::Variables& vars, + const unsigned index) +{ + if (index >= vars.size()) + { + throw InvalidVariableIndexException(this, index); + } +} + + +bool CompoundConstraint::shouldCombineSubConstraints(void) const +{ + return _combineSubConstraints; +} + + +UnsatisfiableConstraintInfo::UnsatisfiableConstraintInfo( + const vpsc::Constraint *c) + : leftVarIndex(c->left->id), + rightVarIndex(c->right->id), + separation(c->gap), + equality(c->equality), + cc((CompoundConstraint *)c->creator) +{ +} + +// Variable mapping. + +VariableIDMap::VariableIDMap() +{ +} + +VariableIDMap::~VariableIDMap() +{ +} + +typedef std::pair<unsigned, unsigned> IDPair; +typedef std::list<IDPair> IDPairList; + +bool VariableIDMap::addMappingForVariable(const unsigned from, + const unsigned to) +{ + bool found = false; + for (IDPairList::iterator it = m_mapping.begin(); it != m_mapping.end(); + ++it) + { + IDPair& ids = *it; + + if (ids.first == from) + { + found = true; + break; + } + } + + if (!found) + { + m_mapping.push_back(std::make_pair(from, to)); + return true; + } + //fprintf(stderr, "VariableIDMap: mapping already exists for var %u\n", from); + return false; +} + +void VariableIDMap::printCreationCode(FILE *fp) const +{ + fprintf(fp, " cola::VariableIDMap idMap;\n"); + for (IDPairList::const_iterator it = m_mapping.begin(); + it != m_mapping.end(); ++it) + { + fprintf(fp, " idMap.addMappingForVariable(%u, %u);\n", + it->first, it->second); + } + fprintf(fp, " \n"); +} + +unsigned VariableIDMap::mappingForVariable(const unsigned var, + bool forward) const +{ + for (IDPairList::const_iterator it = m_mapping.begin(); + it != m_mapping.end(); ++it) + { + const IDPair& ids = *it; + + if (forward) + { + if (ids.first == var) + { + return ids.second; + } + } + else // (!forward) + { + if (ids.second == var) + { + return ids.first; + } + } + } + + //fprintf(stderr, "Warning: mapping not found for var %u\n", var); + + // Just return original variable index. + return var; +} + +void VariableIDMap::clear(void) +{ + m_mapping.clear(); +} + + +} // namespace cola + diff --git a/src/3rdparty/adaptagrams/libcola/compound_constraints.h b/src/3rdparty/adaptagrams/libcola/compound_constraints.h new file mode 100644 index 0000000..4d24152 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/compound_constraints.h @@ -0,0 +1,829 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef _COMPOUND_CONSTRAINTS_H +#define _COMPOUND_CONSTRAINTS_H + +#include <vector> +#include <list> +#include <set> +#include <utility> + +#include "libvpsc/rectangle.h" +#include "libvpsc/constraint.h" +#include "libcola/sparse_matrix.h" +#include "libcola/unused.h" + +namespace vpsc { + class Constraint; + class Variable; + +// Avoid SWIG redefinition warnings. +#ifndef SWIG + typedef std::vector<vpsc::Constraint *> Constraints; + typedef std::vector<vpsc::Variable *> Variables; +#endif +} +namespace cola { + +class Cluster; +class RootCluster; + + +// A component of a CompoundConstraint. +class SubConstraint +{ + public: + SubConstraint(vpsc::Dim dim, vpsc::Constraint constraint, + double cost = 0) + : dim(dim), + constraint(constraint), + cost(cost) + { + } + bool operator<(const SubConstraint& rhs) const + { + return cost < rhs.cost; + } + + vpsc::Dim dim; + vpsc::Constraint constraint; + double cost; +}; + + +// A list of alternative SubConstraints. +typedef std::list<SubConstraint> SubConstraintAlternatives; + +static const double freeWeight = 0.0001; + +static const unsigned int DEFAULT_CONSTRAINT_PRIORITY = 30000; +static const unsigned int PRIORITY_NONOVERLAP = + DEFAULT_CONSTRAINT_PRIORITY - 2000; + +/** + * @brief Holds a mapping between two sets of Variable indices. + * + * This can be used to rewrite the Rectangles to which a set of + * CompoundConstraints apply to. This is useful when creating another + * instance of the problem, but using the same CompoundConstraints list. + * You should not usually need to use this yourself. It is utilised by + * addons such as topology::AvoidTopologyAddon. + * + * If a mapping for a particular value is not set, it is considered to be + * equal on both sides of the mapping. + */ +class VariableIDMap +{ + public: + VariableIDMap(); + ~VariableIDMap(); + + /** + * @brief Adds a mapping between a pair of variables. + * + * @param[in] from The variable index to map from. + * @param[in] to The variable index to map to. + * @return True if the mapping was successfully added. + */ + bool addMappingForVariable(const unsigned from, const unsigned to); + unsigned mappingForVariable(const unsigned var, + bool forward = true) const; + void clear(void); + void printCreationCode(FILE *fp) const; + + private: + std::list<std::pair<unsigned, unsigned> > m_mapping; +}; + +class SubConstraintInfo +{ + public: + SubConstraintInfo(unsigned ind) : + varIndex(ind), + satisfied(false) + { + } + virtual ~SubConstraintInfo() + { + } + virtual void updateVarIDsWithMapping(const VariableIDMap& idMap, + bool forward); + + unsigned varIndex; + bool satisfied; +}; + +typedef std::vector<SubConstraintInfo *> SubConstraintInfoList; + + +/** + * @brief An abstract base class for all high-level compound constraints. + * + * A compound constraint is a conceptual, diagramming application oriented + * type of constraint, which can be translated into a set of simple + * separation constraints, possibly extra dummy variables, and perhaps + * even some extra terms for the quadratic objective function used + * in the gradient projection solver. + */ +class CompoundConstraint { +public: + CompoundConstraint(vpsc::Dim primaryDim, + unsigned int priority = DEFAULT_CONSTRAINT_PRIORITY); + /** + * @brief Implemented by the compound constraint to generate any + * additional required variables in the given dimension. + * + * Generate any additional variables required by this compound constraint + * when operating in the given dimension dim and add them to vars. These + * variables should be cleaned up by the caller after the VPSC problem is + * solved. + * + * The variables' ideal position and weight should be set by the compound + * constraint and they should be added to the end of vars. + * + * @param[in] dim The current active dimension. + * @param[in,out] vars The list of variables for the overall problem + * instance to which any variables generated should + * be appended. + */ + virtual void generateVariables(const vpsc::Dim dim, + vpsc::Variables& vars) = 0; + /** + * @brief Implemented by the compound constraint to generate the low-level + * separation constraints in the given dimension. + * + * These constraints will be added to the list of constraints cs. + * + * @param[in] dim The current active dimension. + * @param[in] vars The list of variables for the overall problem + * instance. + * @param[in,out] cs The list of constraints to which the generated + * constraints will be added. + * @param[in] bbs The list of bounding boxes for all rectangles + * in the current problem. It has the same order as + * vars. + */ + virtual void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& var, vpsc::Constraints& cs, + vpsc::Rectangles& bbs) = 0; + /** + * @brief Implemented by the compound constraint to send position + * information back to the interface. + * + * This will be called for each compound constraint once the VPSC + * instance is solved to allow them to pass information such as + * variable values back to the graphical user interface. + * + * @param[in] dim The current active dimension. + */ + virtual void updatePosition(const vpsc::Dim dim) + { + COLA_UNUSED(dim); + } + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + virtual std::string toString(void) const = 0; + +// To prevent C++ objects from being destroyed in garbage collected languages +// when the libraries are called from SWIG, we hide the declarations of the +// destructors and prevent generation of default destructors. +#ifndef SWIG + virtual ~CompoundConstraint(); +#endif + + vpsc::Dim dimension(void) const; + unsigned int priority(void) const; + virtual void updateVarIDsWithMapping(const VariableIDMap& idMap, + bool forward = true); + virtual void updateShapeOffsetsForDifferentCentres( + const std::vector<double>& offsets, bool forward = true) + { + COLA_UNUSED(offsets); + COLA_UNUSED(forward); + } + + // The following methods are only needed for initially solving feasibility + // of the constraints, and do not need to be implemented for most compound + // constraints. + virtual void markAllSubConstraintsAsInactive(void); + virtual bool subConstraintsRemaining(void) const; + virtual void markCurrSubConstraintAsActive(const bool satisfiable); + virtual SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]) = 0; + std::list<unsigned> subConstraintObjIndexes(void) const; + virtual void printCreationCode(FILE *fp) const; + bool shouldCombineSubConstraints(void) const; + +protected: + void assertValidVariableIndex(const vpsc::Variables& vars, + const unsigned index); + + // The dimension that this compound constraint operates. + vpsc::Dim _primaryDim; + // The alternate dimension. + vpsc::Dim _secondaryDim; + // The priority used to assign order for solving constraints. + unsigned int _priority; + // Describes whether to process sub constraints individually, or all + // at once, during the makeFeasible opteration. + bool _combineSubConstraints; + + // Info about the sub constraints within this compound constraint. + SubConstraintInfoList _subConstraintInfo; + // The index of the current subConstraint being made feasible. + size_t _currSubConstraintIndex; +}; +//! @brief A vector of pointers to CompoundConstraint objects. +typedef std::vector<CompoundConstraint *> CompoundConstraints; + + +/** + * @brief Generate all the variables and constraints for a collection of + * CompoundConstraints. + */ +void generateVariablesAndConstraints(CompoundConstraints& ccs, + const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& cs, + vpsc::Rectangles& bbs); + + +/** + * @brief Generate just all the variables for a collection of + * CompoundConstraints. + */ +void generateVariables(CompoundConstraints& ccs, const vpsc::Dim dim, + vpsc::Variables& vars); + + +/** + * @brief A boundary constraint specifies a bounding line that a set of nodes + * must be either to the left or right of. + * + * A boundary constraint gives a bounding line in a particular dimension (with + * position stored in a variable) and a set of nodes required to be to the left + * of that line and nodes required to be to the right of the line. Separations + * are determined by offsets passed to addShape(). + */ +class BoundaryConstraint : public CompoundConstraint +{ + public: + /** + * @brief Constructs a new BoundaryConstraint in the specified + * dimension. + * + * @param[in] dim The dimension the constraints will operate in. + */ + BoundaryConstraint(const vpsc::Dim dim); + /** + * @brief Mark a node as being part of this boundary constraint. + * + * @param[in] index The index of the node in the Rectangles vector. + * @param[in] offset The minimum amount to separate the node from the + * boundary line. Negative if left-of, positive if + * right-of. Will usually be equal to half a node's + * size plus a buffer amount. + */ + void addShape(const unsigned int index, const double offset); + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + std::string toString(void) const; + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& cs, + vpsc::Rectangles& bbs); + void updatePosition(const vpsc::Dim dim); + void printCreationCode(FILE *fp) const; + + //! Holds the position of the boundary line, once layout is complete. + double position; + + vpsc::Variable* variable; +}; + + +/** + * @brief An alignment constraint specifies a alignment line that a set of + * nodes must be constrained to by an exact amount. + * + * This is represented as a variable representing the position of a vertical + * or horizontal and a then group of nodes and offsets for those nodes such + * that the nodes must be spaced exactly at those offsets from the alignment + * position. + * + * Optionally, the alignment may be given a suggested position and/or marked + * as "fixed". When fixed, the position variable will be given a higher + * weight to attempt to keep it at that position. + */ +class AlignmentConstraint : public CompoundConstraint +{ + public: + /** + * @brief Constructs a new AlignmentConstraint in the specified + * dimension. + * + * @param[in] dim The dimension the constraints will operate in. + */ + AlignmentConstraint(const vpsc::Dim dim, double position = 0.0); + /** + * @brief Mark a node as being part of this alignment constraint. + * + * @param[in] index The index of the node in the Rectangles vector. + * @param[in] offset The exact amount to separate the node from the + * alignment line. Negative if left-of, positive if + * right-of. Will usually be equal to half a node's + * size if aligning to the side of a node, or zero + * if aligning with the centre of a node. + */ + void addShape(const unsigned int index, const double offset); + /** + * @brief Mark the alignment as ideally having a fixed position. + * + * This causes the position variable for the alignment to be given + * the ideal position pos and a higher weight. + * + * @param[in] pos The ideal position value for the alignment. + */ + void fixPos(double pos); + /** + * @brief Mark the alignment as not having a fixed position. + * + * This is the default. + */ + void unfixPos(void); + /** + * @brief Indicates if the alignment position is marked as fixed. + * + * @returns True if the alignment position is marked as fixed, or + * false otherwise. + */ + bool isFixed(void) const; + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + std::string toString(void) const; + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& cs, + vpsc::Rectangles& bbs); + void updatePosition(const vpsc::Dim dim); + double position(void) const; + void printCreationCode(FILE *fp) const; + void updateShapeOffsetsForDifferentCentres( + const std::vector<double>& offsets, bool forward = true); + + /// Generic pointer to an indicator object being used to represent + /// this compound constraint in the GUI. + void *indicator; + + vpsc::Variable* variable; + private: + // The position of the alignment line + double _position; + bool _isFixed; +}; + + +/** + * @brief A separation constraint specifies a simple horizontal or vertical + * spacing constraint between 2 nodes or alignment constraints. + * + * The non-equality constraint is lPos + g <= rPos + * and the equality constraint is lPos + g = rPos + * + * @note With an equality, you can effectively reverse the ordering of the + * two variables by making the gap a negative number. This is not so + * for the non-equality case, there you need to keep the same gap value + * but reverse the order of the variables passed to the constructor. + */ +class SeparationConstraint : public CompoundConstraint +{ + public: + /** + * @brief Constructs a new SeparationConstraint between two nodes in + * the specified dimension. + * + * The constraint will keep the centre of the left node to the left of + * the right node by exactly or more than the specified gap. + * + * @param[in] dim The dimension the constraint will operate in. + * @param[in] l The index of the left node. + * @param[in] r The index of the right node. + * @param[in] g The minimum or exact distance to separate the + * two nodes. + * @param[in] equality Whether or not the constraint is an exact + * distance. + */ + SeparationConstraint(const vpsc::Dim dim, unsigned l, unsigned r, + double g, bool equality = false); + /** + * @brief Constructs a new SeparationConstraint between two alignment + * constraints in the specified dimension. + * + * The constraint will keep the centre of the left alignment line to + * the left of the right alignment line by exactly or more than the + * specified gap. + * + * @param[in] dim The dimension the constraint will operate in. + * @param[in] l A pointer to the left AlignmentConstraint. + * @param[in] r A pointer to the right AlignmentConstraint. + * @param[in] g The minimum or exact distance to separate the + * two alignment constraints. + * @param[in] equality Whether or not the constraint is an exact + * distance. + */ + SeparationConstraint(const vpsc::Dim dim, AlignmentConstraint *l, + AlignmentConstraint *r, double g, bool equality = false); + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + std::string toString(void) const; + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vs, vpsc::Constraints& cs, + vpsc::Rectangles& bbs); + void setSeparation(double gap); + unsigned left(void) const; + unsigned right(void) const; + void printCreationCode(FILE *fp) const; + + double gap; + bool equality; + vpsc::Constraint *vpscConstraint; +}; + + +// XXX: This is experimental +// +// Orthogonal edges must have their end points aligned horizontally or +// vertically +class OrthogonalEdgeConstraint : public CompoundConstraint +{ + public: + OrthogonalEdgeConstraint(const vpsc::Dim dim, unsigned l, unsigned r); + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vs, vpsc::Constraints& cs, + vpsc::Rectangles& bbs); + void generateTopologyConstraints(const vpsc::Dim k, + vpsc::Rectangles const& rs, + std::vector<vpsc::Variable*> const& vars, + std::vector<vpsc::Constraint*>& cs); + void printCreationCode(FILE *fp) const; + std::string toString(void) const; + + unsigned left; + unsigned right; + vpsc::Constraint* vpscConstraint; + private: + void rectBounds(const vpsc::Dim k, vpsc::Rectangle const *r, + double& cmin, double& cmax, double& centre, double& l) const; +}; + + +/** + * @brief A multi-separation constraint Specifies a set of horizontal or + * vertical equal spacing constraints between pairs of alignment + * constraints. + * + * This is a way of arranging a group of alignment lines to be equally + * distributed, or given a uniform minimum spacing. + */ +class MultiSeparationConstraint : public CompoundConstraint +{ + public: + /** + * @brief Constructs a new empty MultiSeparationConstraint with a + * minimum or exact spacing. + * + * @param[in] dim The dimension the constraints will operate in. + * @param[in] minSep The minimum or exact distance to separate the + * alignment constraints. + * @param[in] equality Whether or not the constraints will be an exact + * distance. + */ + MultiSeparationConstraint(const vpsc::Dim dim, double minSep = 0, + bool equality = false); + /** + * @brief Mark a pair of alignment constraints as being part of this + * multi separation constraint. + * + * You will often specify spacing beteen a set of alignments (e.g., + * {1, 2, 3, 4}) by calling this method with each neighbouring pair + * (e.g., {(1, 2), (2, 3), (3, 4)}), but you can also specify + * non-neighbouring alignment constraints, if you wish them to have + * equal exact or minimum separation. + * + * @param[in] ac1 A pointer to the left AlignmentConstraint object + * of the pair. + * @param[in] ac2 A pointer to the right AlignmentConstraint object + * of the pair. + */ + void addAlignmentPair(AlignmentConstraint *ac1, + AlignmentConstraint *ac2); + /** + * @brief Alter the minimum or exact spacing between each pair of + * alignment constraints. + * + * @param[in] sep The minimum or exact distance to separate the + * alignment constraints. + */ + void setSeparation(double sep); + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + std::string toString(void) const; + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vs, vpsc::Constraints& gcs, + vpsc::Rectangles& bbs); + void printCreationCode(FILE *fp) const; + + vpsc::Constraints cs; + + /// Generic pointer to an indicator object being used to represent + /// this compound constraint in the GUI. + void *indicator; + + double sep; + bool equality; +}; + + +/** + * @brief A distribution constraint specifies an ordered set of alignment + * constraints and a fixed separation required between them. + * + * This compound constraint it used to keep a set of alignment constraints + * equally distributed. + * + * If no separation distance is set, then it is detemined from the distance + * between the two outer alignments, divided by the number of alignments - 1. + */ +class DistributionConstraint : public CompoundConstraint { + public: + /** + * @brief Constructs a new empty DistributionConstraint with a + * minimum or exact spacing. + * + * @param[in] dim The dimension the constraints will operate in. + */ + DistributionConstraint(const vpsc::Dim dim); + /** + * @brief Mark a pair of alignment constraints as being part of this + * distribution constraint. + * + * You should specify spacing beteen a set of alignments (e.g., + * {1, 2, 3, 4}) by calling this method with each neighbouring pair + * (e.g., {(1, 2), (2, 3), (3, 4)}). + * + * @param[in] ac1 A pointer to the left AlignmentConstraint object + * of the pair. + * @param[in] ac2 A pointer to the right AlignmentConstraint object + * of the pair. + */ + void addAlignmentPair(AlignmentConstraint *ac1, + AlignmentConstraint *ac2); + /** + * @brief Alter the exact spacing between each pair of alignment + * constraints. + * + * @param[in] sep The exact distance to separate the alignment + * constraints. + */ + void setSeparation(double sep); + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + std::string toString(void) const; + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& gcs, + vpsc::Rectangles& bbs); + void printCreationCode(FILE *fp) const; + + vpsc::Constraints cs; + + /// Generic pointer to an indicator object being used to represent + /// this compound constraint in the GUI. + void *indicator; + + double sep; +}; + +/** + * @brief A fixed-relative constraint specifies that a group of nodes are + * constrained to be fixed in position relative to each other. + * + * These nodes are fixed relative to each other in both the x- and y-dimensions + * but still free to move as a group. + * + * Optionally, this compound constraint can be marked as desiring a fixed + * position. If this is specified, the group of nodes will attempt to stay + * close to its current position. + */ +class FixedRelativeConstraint : public CompoundConstraint { + public: + /** + * @brief Constructs a new FixedRelativeConstraint between a set of + * nodes, optionally with a fixed position. + * + * @param[in] rs The list of bounding boxes for the rectangles + * for all nodes in the current problem. + * @param[in] shapeIds A vector of indices into the rc vector for the + * nodes that will be fixed relative to each other. + * @param[in] fixedPosition Whether of not the nodes should ideally be + * fixed to the current position. The default + * is not fixed. + */ + FixedRelativeConstraint(const vpsc::Rectangles& rs, + std::vector<unsigned> shapeIds, + const bool fixedPosition = false); + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + std::string toString(void) const; + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& gcs, + vpsc::Rectangles& bbs); + void printCreationCode(FILE *fp) const; + void updateVarIDsWithMapping(const VariableIDMap& idMap, + bool forward = true); + + private: + bool m_fixed_position; + std::vector<unsigned> m_shape_vars; +}; + + +/** + * @brief A page boundary contraint specifies constraints that attempt to keep + * the given nodes within a defined rectangular region. + * + * This compound constraint creates dummy variables for each of the four edges + * of the page and constraints between all nodes and these dummy vars such + * that nodes are contained between the edges. The variables for the page + * edges have a high weight but will "balloon out" if other constraints force + * nodes to stick out past the ideal edge positions. + */ +class PageBoundaryConstraints : public CompoundConstraint { + public: + /** + * @brief Constructs a new PageBoundaryConstraints object with given + * page boundary positions and weight. + * + * @param[in] xLow The position of the left edge of the page. + * @param[in] xHigh The position of the right edge of the page. + * @param[in] yLow The position of the bottom edge of the page. + * @param[in] yHigh The position of the top edge of the page. + * @param[in] weight The weight to give the positions variables + * for the page edges. The default is 100.0. + */ + PageBoundaryConstraints(double xLow, double xHigh, + double yLow, double yHigh, double weight = 100.0); + /** + * @brief Mark a node as being contained within this page boundary. + * + * @param[in] index The index of the node in the Rectangles vector. + * @param[in] halfW Half of the width of the node. Needed because + * node position variables represent their centre. + * @param[in] halfH Half of the height of the node. + */ + void addShape(unsigned index, double halfW, double halfH); + + /** + * @brief Returns a textual description of the compound constraint. + * + * @return A string describing the compound constraint. + */ + std::string toString(void) const; + + SubConstraintAlternatives getCurrSubConstraintAlternatives( + vpsc::Variables vs[]); + void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars); + void generateSeparationConstraints(const vpsc::Dim dim, + vpsc::Variables& vars, vpsc::Constraints& gcs, + vpsc::Rectangles& bbs); + void updatePosition(const vpsc::Dim dim); + double getActualLeftMargin(const vpsc::Dim dim); + double getActualRightMargin(const vpsc::Dim dim); + void printCreationCode(FILE *fp) const; + + private: + double leftMargin[2]; + double rightMargin[2]; + double actualLeftMargin[2]; + double actualRightMargin[2]; + double leftWeight[2]; + double rightWeight[2]; + vpsc::Variable *vl[2], *vr[2]; +}; + + +/** + * @brief Info about constraints that could not be satisfied in gradient + * projection process. + */ +class UnsatisfiableConstraintInfo { + public: + UnsatisfiableConstraintInfo(const vpsc::Constraint* c); + + //! The index of the left variable. + unsigned leftVarIndex; + //! The index of the right variable. + unsigned rightVarIndex; + //! The separation. + double separation; + //! Whether the separation is an exact distance or not. + bool equality; + //! The index of the CompoundConstraint that created this. + cola::CompoundConstraint *cc; + + std::string toString(void) const + { + std::stringstream stream; + stream << "Unsatisfiable constraint: var(" << leftVarIndex << ") "; + if (separation < 0) + { + stream << "- " << -separation; + } + else + { + stream << "+ " << separation; + } + stream << " " << ((equality) ? "== " : "<= "); + stream << "var(" << rightVarIndex << ")"; + if (cc) + { + stream << "\n From " << cc->toString(); + } + + return stream.str(); + } +}; +//! @brief A vector of pointers to UnsatisfiableConstraintInfo objects. +typedef std::vector<UnsatisfiableConstraintInfo *> UnsatisfiableConstraintInfos; + +} // namespace cola +#endif // _COMPOUND_CONSTRAINTS_H diff --git a/src/3rdparty/adaptagrams/libcola/conjugate_gradient.cpp b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.cpp new file mode 100644 index 0000000..adb7fa6 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.cpp @@ -0,0 +1,137 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006 Nathan Hurst <njh@njhurst.com> + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Nathan Hurst + * Tim Dwyer + * +*/ + + +#include <cmath> +#include <cstdlib> +#include <cassert> +#include <valarray> + +#include "libvpsc/assertions.h" +#include "libcola/commondefs.h" +#include "libcola/conjugate_gradient.h" + +/* lifted wholely from wikipedia. Well, apart from the bug in the wikipedia version. */ + +using std::valarray; + +static void +matrix_times_vector(valarray<double> const &matrix, /* m * n */ + valarray<double> const &vec, /* n */ + valarray<double> &result) /* m */ +{ + unsigned n = vec.size(); + unsigned m = result.size(); + COLA_ASSERT(m*n == matrix.size()); +# if defined(_MSC_VER) + // magmy: The following lines show how operator[] is defined for valarray under MSVC + // _Ty valarray<_Ty>::operator[](size_t _Off) const; + // _Ty &valarray<_Ty>::operator[](size_t _Off); + // As a consequence, it is not possible to take the address of a constant valarray[n]. + // This looks like a bug in the Microsoft's <valarray> file. + // Below is a workaround + double const *mp = &const_cast<valarray<double> &>(matrix)[0]; +# else + const double* mp = &matrix[0]; +# endif + for (unsigned i = 0; i < m; i++) { + double res = 0; + for (unsigned j = 0; j < n; j++) + res += *mp++ * vec[j]; + result[i] = res; + } +} + +/* +static double Linfty(valarray<double> const &vec) { + return std::max(vec.max(), -vec.min()); +} +*/ + +double +inner(valarray<double> const &x, + valarray<double> const &y) { + double total = 0; + for(unsigned i = 0; i < x.size(); i++) + total += x[i]*y[i]; + return total;// (x*y).sum(); <- this is more concise, but ineff +} + +double compute_cost(valarray<double> const &A, + valarray<double> const &b, + valarray<double> const &x, + const unsigned n) { + // computes cost = 2 b x - x A x + double cost = 2. * inner(b,x); + valarray<double> Ax(n); + for (unsigned i=0; i<n; i++) { + Ax[i] = 0; + for (unsigned j=0; j<n; j++) { + Ax[i] += A[i*n+j]*x[j]; + } + } + return cost - inner(x,Ax); +} +void +conjugate_gradient(valarray<double> const &A, + valarray<double> &x, + valarray<double> const &b, + unsigned const n, double const tol, + unsigned const max_iterations) { + //printf("Conjugate Gradient...\n"); + valarray<double> Ap(n), p(n), r(n); + matrix_times_vector(A,x,Ap); + r=b-Ap; + double r_r = inner(r,r); + unsigned k = 0; + double tol_squared = tol*tol; +#ifdef EXAMINE_COST + double previousCost=compute_cost(A,b,x,n),cost; +#endif + while(k < max_iterations && r_r > tol_squared) { + k++; + double r_r_new = r_r; + if(k == 1) + p = r; + else { + r_r_new = inner(r,r); + if(r_r_new<tol_squared) break; + p = r + (r_r_new/r_r)*p; + } + matrix_times_vector(A, p, Ap); + double alpha_k = r_r_new / inner(p, Ap); + x += alpha_k*p; +#ifdef EXAMINE_COST + cost=compute_cost(A,b,x,n); + printf(" CG[%d] %.15f %.15f\n",k,previousCost,cost); + previousCost=cost; +#endif + r -= alpha_k*Ap; + r_r = r_r_new; + } + //printf(" CG finished after %d iterations\n",k); + //printf("njh: %d iters, Linfty = %g L2 = %g\n", k, + //std::max(-r.min(), r.max()), sqrt(r_r)); + // x is solution +} diff --git a/src/3rdparty/adaptagrams/libcola/conjugate_gradient.h b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.h new file mode 100644 index 0000000..e21cd16 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.h @@ -0,0 +1,36 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef _CONJUGATE_GRADIENT_H +#define _CONJUGATE_GRADIENT_H + +#include <valarray> + +double +inner(std::valarray<double> const &x, + std::valarray<double> const &y); + +void +conjugate_gradient(std::valarray<double> const &A, + std::valarray<double> &x, + std::valarray<double> const &b, + unsigned const n, double const tol, + unsigned const max_iterations); +#endif // _CONJUGATE_GRADIENT_H diff --git a/src/3rdparty/adaptagrams/libcola/connected_components.cpp b/src/3rdparty/adaptagrams/libcola/connected_components.cpp new file mode 100644 index 0000000..fc65dc9 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/connected_components.cpp @@ -0,0 +1,160 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + + +#include <map> +#include <list> + +#include "libvpsc/rectangle.h" +#include "libvpsc/assertions.h" +#include "libcola/commondefs.h" +#include "libcola/connected_components.h" + +using namespace std; +using namespace vpsc; +namespace cola { + Component::~Component() { + /* + for(unsigned i=0;i<scx.size();i++) { + delete scx[i]; + } + for(unsigned i=0;i<scy.size();i++) { + delete scy[i]; + } + */ + } + void Component::moveRectangles(double x, double y) { + for(unsigned i=0;i<rects.size();i++) { + rects[i]->moveCentreX(rects[i]->getCentreX()+x); + rects[i]->moveCentreY(rects[i]->getCentreY()+y); + } + } + Rectangle* Component::getBoundingBox() + { + Rectangle boundingBox; + for (unsigned i = 0; i < rects.size(); ++i) + { + boundingBox = boundingBox.unionWith(*(rects[i])); + } + return new Rectangle(boundingBox); + } + + namespace ccomponents { + struct Node { + unsigned id; + bool visited; + vector<Node*> neighbours; + list<Node*>::iterator listPos; + Rectangle* r; + }; + // Depth first search traversal of graph to find connected component + void dfs(Node* v, + list<Node*>& remaining, + Component* component, + map<unsigned,pair<Component*,unsigned> > &cmap) { + v->visited=true; + remaining.erase(v->listPos); + cmap[v->id]=make_pair(component,static_cast<unsigned>(component->node_ids.size())); + component->node_ids.push_back(v->id); + component->rects.push_back(v->r); + for(unsigned i=0;i<v->neighbours.size();i++) { + Node* u=v->neighbours[i]; + if(!u->visited) { + dfs(u,remaining,component,cmap); + } + } + } + } + + using namespace ccomponents; + + // for a graph of n nodes, return connected components + void connectedComponents( + const vector<Rectangle*> &rs, + const vector<Edge> &es, + //const SeparationConstraints &scx, + //const SeparationConstraints &scy, + vector<Component*> &components) { + unsigned n=rs.size(); + vector<Node> vs(n); + list<Node*> remaining; + for(unsigned i=0;i<n;i++) { + vs[i].id=i; + vs[i].visited=false; + vs[i].r=rs[i]; + vs[i].listPos = remaining.insert(remaining.end(),&vs[i]); + } + vector<Edge>::const_iterator ei; + for(ei=es.begin();ei!=es.end();ei++) { + vs[ei->first].neighbours.push_back(&vs[ei->second]); + vs[ei->second].neighbours.push_back(&vs[ei->first]); + } + map<unsigned,pair<Component*,unsigned> > cmap; + while(!remaining.empty()) { + Component* component=new Component; + Node* v=*remaining.begin(); + dfs(v,remaining,component,cmap); + components.push_back(component); + } + for(ei=es.begin();ei!=es.end();ei++) { + pair<Component*,unsigned> u=cmap[ei->first], + v=cmap[ei->second]; + COLA_ASSERT(u.first==v.first); + u.first->edges.push_back(make_pair(u.second,v.second)); + } + /* + SeparationConstraints::const_iterator ci; + for(ci=scx.begin();ci!=scx.end();ci++) { + SeparationConstraint *c=*ci; + pair<Component*,unsigned> u=cmap[c->left], + v=cmap[c->right]; + COLA_ASSERT(u.first==v.first); + u.first->scx.push_back( + new SeparationConstraint(u.second,v.second,c->gap)); + } + for(ci=scy.begin();ci!=scy.end();ci++) { + SeparationConstraint *c=*ci; + pair<Component*,unsigned> u=cmap[c->left], + v=cmap[c->right]; + COLA_ASSERT(u.first==v.first); + u.first->scy.push_back( + new SeparationConstraint(u.second,v.second,c->gap)); + } + */ + } + void separateComponents(const vector<Component*> &components) { + unsigned n=components.size(); + vector<Rectangle*> bbs(n); + valarray<double> origX(n); + valarray<double> origY(n); + for(unsigned i=0;i<n;i++) { + bbs[i]=components[i]->getBoundingBox(); + origX[i]=bbs[i]->getCentreX(); + origY[i]=bbs[i]->getCentreY(); + } + removeoverlaps(bbs); + for(unsigned i=0;i<n;i++) { + components[i]->moveRectangles( + bbs[i]->getCentreX()-origX[i], + bbs[i]->getCentreY()-origY[i]); + delete bbs[i]; + } + } +} diff --git a/src/3rdparty/adaptagrams/libcola/connected_components.h b/src/3rdparty/adaptagrams/libcola/connected_components.h new file mode 100644 index 0000000..578eab2 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/connected_components.h @@ -0,0 +1,54 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef CONNECTED_COMPONENTS_H +#define CONNECTED_COMPONENTS_H +#include "libcola/cola.h" +#include <vector> + +namespace cola { +// a graph component with a list of node_ids giving indices for some larger list of nodes +// for the nodes in this component, +// and a list of edges - node indices relative to this component +class Component { +public: + std::vector<unsigned> node_ids; + std::vector<vpsc::Rectangle*> rects; + std::vector<cola::Edge> edges; + //CompoundConstraints cx, cy; + ~Component(); + void moveRectangles(double x, double y); + vpsc::Rectangle* getBoundingBox(); +}; +// for a graph of n nodes, return connected components +void connectedComponents( + const std::vector<vpsc::Rectangle*> &rs, + const std::vector<cola::Edge> &es, + //const CompoundConstraints &cx, + //const CompoundConstraints &cy, + std::vector<Component*> &components); + +// move the contents of each component so that the components do not +// overlap. +void separateComponents(const std::vector<Component*> &components); + +} // namespace cola + +#endif // CONNECTED_COMPONENTS_H diff --git a/src/3rdparty/adaptagrams/libcola/convex_hull.cpp b/src/3rdparty/adaptagrams/libcola/convex_hull.cpp new file mode 100644 index 0000000..3ecbfea --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/convex_hull.cpp @@ -0,0 +1,129 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#include <valarray> +#include <cfloat> +#include <algorithm> + +#include "libvpsc/assertions.h" +#include "libcola/convex_hull.h" + + +namespace hull { +using namespace std; +/** + * CrossProduct of three points: If the result is 0, the points are collinear; + * if it is positive, the three points (in order) constitute a "left turn", + * otherwise a "right turn". + */ +inline double crossProduct( + double x0, double y0, + double x1, double y1, + double x2, double y2) { + return (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0); +} +struct CounterClockwiseOrder { + CounterClockwiseOrder( + const unsigned p, + std::valarray<double> const & X, std::valarray<double> const & Y) + :px(X[p]), py(Y[p]), X(X), Y(Y) {}; + bool operator() (unsigned i, unsigned j) { + // o=crossProduct(px,py,X[i],Y[i],X[j],Y[j]); + double xi=X[i]-px; + double xj=X[j]-px; + // since py is the min y pos, yi and yj must be positive + double yi=Y[i]-py; + double yj=Y[j]-py; + + // use cross product rule + double o = xi*yj-xj*yi; + if(o!=0) { + return o>0; + } + // in case of ties choose point farthest from p + return (xi*xi+yi*yi) < (xj*xj+yj*yj); + } + const double px; + const double py; + std::valarray<double> const & X; + std::valarray<double> const & Y; +}; +void convex(const unsigned n, const double* X, const double* Y, vector<unsigned> & h) { + const valarray<double> XA(X,n); + const valarray<double> YA(Y,n); + convex(XA,YA,h); +} +/** + * Implementation of Graham's scan convex hull finding algorithm. + * X and Y give the horizontal and vertical positions of the pointset. + * The result is returned in hull as a list of indices referencing points in X and Y. + */ +void convex(valarray<double> const & X, valarray<double> const & Y, vector<unsigned> & h) { + unsigned n=X.size(); + COLA_ASSERT(n==Y.size()); + unsigned p0=0; + // find point p0 with min Y position, choose leftmost in case of tie. + // This is our "pivot" point + double minY=DBL_MAX,minX=DBL_MAX; + for(unsigned i=0;i<n;i++) { + if ( (Y[i] < minY) || ((Y[i] == minY) && (X[i] < minX)) ) + { + p0=i; + minY=Y[i]; + minX=X[i]; + } + } + // sort remaining points by the angle line p0-p1 (p1 in points) makes + // with x-axis + vector<unsigned> points; + for(unsigned i=0;i<n;i++) { + if(i!=p0) points.push_back(i); + } + CounterClockwiseOrder order(p0,X,Y); + sort(points.begin(),points.end(),order); + // now we maintain a stack in h, adding points while each successive + // point is a "left turn", backtracking if we make a right turn. + h.clear(); + h.push_back(p0); + h.push_back(points[0]); + for(unsigned i=1;i<points.size();i++) { + double o=crossProduct( + X[h[h.size()-2]],Y[h[h.size()-2]], + X[h[h.size()-1]],Y[h[h.size()-1]], + X[points[i]],Y[points[i]]); + if(o==0) { + h.pop_back(); + h.push_back(points[i]); + } else if(o>0) { + h.push_back(points[i]); + } else { + while(o<=0 && h.size()>2) { + h.pop_back(); + o=crossProduct( + X[h[h.size()-2]],Y[h[h.size()-2]], + X[h[h.size()-1]],Y[h[h.size()-1]], + X[points[i]],Y[points[i]]); + } + h.push_back(points[i]); + } + } +} + +} // namespace hull diff --git a/src/3rdparty/adaptagrams/libcola/convex_hull.h b/src/3rdparty/adaptagrams/libcola/convex_hull.h new file mode 100644 index 0000000..e17c6a8 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/convex_hull.h @@ -0,0 +1,31 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef CONVEX_HULL_H +#define CONVEX_HULL_H +#include <vector> +#include <valarray> + +namespace hull { +void convex(const unsigned n, const double* X, const double* Y, std::vector<unsigned> & hull); +void convex(const std::valarray<double> & X, const std::valarray<double> & Y, std::vector<unsigned> & hull); +} + +#endif // CONVEX_HULL_H diff --git a/src/3rdparty/adaptagrams/libcola/doc/description.doc b/src/3rdparty/adaptagrams/libcola/doc/description.doc new file mode 100644 index 0000000..cf8cdda --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/doc/description.doc @@ -0,0 +1,50 @@ +/*! + +\if LIBCOLA_DOC +@mainpage libcola: Force-directed Network Layout ubject to Separation Constraints +\endif +\if ADAPTAGRAMS_DOC +@page libcola libcola — Overview +\endif + +libcola is a cross-platform C++ library for constraint graph layout. Specifically, force-directed layout using the stress-majorization method subject to separation constraints. Applications include layout with non-overlapping nodes and clusters, directed graph layout and layout preserving the crossing properties of a given starting layout. + +libcola is part of the +<a href="http://www.adaptagrams.org/">Adaptagrams project</a>. +There are no official releases yet, though the code is stable and +available from the Adaptagrams +<a href="https://github.com/mjwybrow/adaptagrams">GitHub +repository</a>. + +The API is documented using Doxygen. The documentation you are currently +reading can be obtained by running doxygen in the cola directory. + +libcola is written and maintained by +<a href="http://users.monash.edu/~mwybrow/">Michael Wybrow</a> and +<a href="http://ialab.it.monash.edu/~dwyer/">Tim Dwyer</a>, +members of <a href="http://ialab.it.monash.edu/">Immersive Analytics Lab</a> at Monash University, Australia. + +The algorithms used for ConstrainedFDLayout are described in the following papers. If you use libcola, please cite the relevant paper. +- Tim Dwyer, Kim Marriott, and Michael Wybrow. Topology preserving + constrained graph layout. In Proc. 16th Intl. Symp. Graph Drawing + (GD'08), volume 5417 of Lecture Notes in Computer Science, pages + 230-241. Springer, 2009. +- Tim Dwyer, Kim Marriott, and Michael Wybrow. Dunnart: A + constraint-based network diagram authoring tool. In Proc. 16th Intl. + Symp. Graph Drawing (GD'08), volume 5417 of Lecture Notes in Computer + Science, pages 420-431. Springer, 2009. +- Tim Dwyer, Kim Marriott, Falk Schreiber, Peter J. Stuckey, + Michael Woodward, and Michael Wybrow. Exploration of networks using + overview+detail with constraint-based cooperative layout. IEEE + Transactions on Visualization and Computer Graphics, 14(6):1293-1300, + 2008. + +The method used in ConstrainedMajorizationLayout is described in: +- Tim Dwyer and Kim Marriott. Constrained stress majorization using diagonally + scaled gradient projection. In Proc. 15th Intl. Symp. Graph Drawing (GD + '07), volume 4875 of Lecture Notes in Computer Science. Springer, 2008. + + +*/ + + diff --git a/src/3rdparty/adaptagrams/libcola/exceptions.h b/src/3rdparty/adaptagrams/libcola/exceptions.h new file mode 100644 index 0000000..516e69e --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/exceptions.h @@ -0,0 +1,54 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef SEEN_LIBCOLA_EXCEPTIONS_H +#define SEEN_LIBCOLA_EXCEPTIONS_H +#include <string> +#include <sstream> + +namespace cola { +class CompoundConstraint; + +struct InvalidConstraint { + InvalidConstraint(CompoundConstraint *c):constraint(c) {} + CompoundConstraint *constraint; +}; + + +class InvalidVariableIndexException +{ +public: + InvalidVariableIndexException(CompoundConstraint *c, unsigned i) + : constraint(c), + index(i) + { } + std::string what() const throw() + { + std::stringstream s; + s << "Invalid variable index: " << index; + return s.str(); + } + CompoundConstraint *constraint; + unsigned index; +}; + + +} // namespace cola +#endif //SEEN_LIBCOLA_EXCEPTIONS_H diff --git a/src/3rdparty/adaptagrams/libcola/gradient_projection.cpp b/src/3rdparty/adaptagrams/libcola/gradient_projection.cpp new file mode 100644 index 0000000..b53e876 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/gradient_projection.cpp @@ -0,0 +1,482 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +/********************************************************** + * + * Solve a quadratic function f(X) = X' A X + b X + * subject to a set of separation constraints cs + * + **********************************************************/ + +#include <iostream> +#include <cmath> +#include <ctime> + +#include <libvpsc/solve_VPSC.h> +#include <libvpsc/variable.h> +#include <libvpsc/constraint.h> +#include <libvpsc/assertions.h> + +#include "libcola/cluster.h" +#include "libcola/gradient_projection.h" +#include "libcola/straightener.h" +#include "libcola/commondefs.h" +//#define CHECK_CONVERGENCE_BY_COST 1 + + +using namespace std; +using namespace vpsc; +namespace cola { +GradientProjection::GradientProjection( + const Dim k, + std::valarray<double> *denseQ, + const double tol, + const unsigned max_iterations, + CompoundConstraints const *ccs, + UnsatisfiableConstraintInfos *unsatisfiableConstraints, + NonOverlapConstraintsMode nonOverlapConstraints, + RootCluster* clusterHierarchy, + vpsc::Rectangles* rs, + const bool scaling, + SolveWithMosek solveWithMosek) + : k(k), + denseSize(static_cast<unsigned>((floor(sqrt(static_cast<double>(denseQ->size())))))), + denseQ(denseQ), + rs(rs), + ccs(ccs), + unsatisfiableConstraints(unsatisfiableConstraints), + nonOverlapConstraints(nonOverlapConstraints), + clusterHierarchy(clusterHierarchy), + tolerance(tol), + max_iterations(max_iterations), + sparseQ(nullptr), + solveWithMosek(solveWithMosek), + scaling(scaling) +{ + //printf("GP Instance: scaling=%d, mosek=%d\n",scaling,solveWithMosek); + for(unsigned i=0;i<denseSize;i++) { + vars.push_back(new vpsc::Variable(i,1,1)); + } + if(scaling) { + scaledDenseQ.resize(denseSize*denseSize); + for(unsigned i=0;i<denseSize;i++) { + vars[i]->scale=1./sqrt(fabs((*denseQ)[i*denseSize+i])); + // XXX: Scale can sometimes be set to infinity here when + // there are nodes not connected to any other node. + // Thus we just set the scale for such a variable to 1. + if (!std::isfinite(vars[i]->scale)) + { + vars[i]->scale = 1; + } + } + // the following computes S'QS for Q=denseQ + // and S is diagonal matrix of scale factors + for(unsigned i=0;i<denseSize;i++) { + for(unsigned j=0;j<denseSize;j++) { + scaledDenseQ[i*denseSize+j]=(*denseQ)[i*denseSize+j]*vars[i]->scale + *vars[j]->scale; + } + } + this->denseQ = &scaledDenseQ; + } + //dumpSquareMatrix(*this->denseQ); + //dumpSquareMatrix(scaledDenseQ); + + if(ccs) { + for(CompoundConstraints::const_iterator c=ccs->begin(); + c!=ccs->end();++c) { + (*c)->generateVariables(k, vars); + OrthogonalEdgeConstraint* e=dynamic_cast<OrthogonalEdgeConstraint*>(*c); + if(e) { + orthogonalEdges.push_back(e); + } + } + for(CompoundConstraints::const_iterator c=ccs->begin(); + c!=ccs->end();++c) { + (*c)->generateSeparationConstraints(k, vars, gcs, *rs); + } + } + /* + if(clusterHierarchy) { + clusterHierarchy->createVars(k,*rs,vars); + } + */ + numStaticVars=vars.size(); + //solver=setupVPSC(); +} +static inline double dotProd(valarray<double> const & a, valarray<double> const & b) { + double p = 0; + for (unsigned i=0; i<a.size(); i++) { + p += a[i]*b[i]; + } + return p; +} +double GradientProjection::computeCost( + valarray<double> const &b, + valarray<double> const &x) const { + // computes cost = 2 b x - x A x + double cost = 2. * dotProd(b,x); + valarray<double> Ax(x.size()); + for (unsigned i=0; i<denseSize; i++) { + Ax[i] = 0; + for (unsigned j=0; j<denseSize; j++) { + Ax[i] += (*denseQ)[i*denseSize+j]*x[j]; + } + } + if(sparseQ) { + valarray<double> r(x.size()); + sparseQ->rightMultiply(x,r); + Ax+=r; + } + return cost - dotProd(x,Ax); +} + +double GradientProjection::computeSteepestDescentVector( + valarray<double> const &b, + valarray<double> const &x, + valarray<double> &g) const { + // find steepest descent direction + // g = 2 ( b - A x ) + // where: A = denseQ + sparseQ + // g = 2 ( b - denseQ x) - 2 sparseQ x + // + // except the 2s don't matter because we compute + // the optimal stepsize anyway + COLA_ASSERT(x.size()==b.size() && b.size()==g.size()); + g = b; + for (unsigned i=0; i<denseSize; i++) { + for (unsigned j=0; j<denseSize; j++) { + g[i] -= (*denseQ)[i*denseSize+j]*x[j]; + } + } + // sparse part: + if(sparseQ) { + valarray<double> r(x.size()); + sparseQ->rightMultiply(x,r); + g-=r; + } + return computeStepSize(g,g); +} +// compute optimal step size along descent vector d relative to +// a gradient related vector g +// stepsize = ( g' d ) / ( d' A d ) +double GradientProjection::computeStepSize( + valarray<double> const & g, valarray<double> const & d) const { + COLA_ASSERT(g.size()==d.size()); + valarray<double> Ad; + if(sparseQ) { + Ad.resize(g.size()); + sparseQ->rightMultiply(d,Ad); + } + double const numerator = dotProd(g, d); + double denominator = 0; + for (unsigned i=0; i<g.size(); i++) { + double r = sparseQ ? Ad[i] : 0; + if(i<denseSize) { for (unsigned j=0; j<denseSize; j++) { + r += (*denseQ)[i*denseSize+j] * d[j]; + } } + denominator += r * d[i]; + } + if(denominator==0) { + return 0; + } + return numerator/(2.*denominator); +} + +bool GradientProjection::runSolver(valarray<double> & result) { + bool activeConstraints = false; + switch(solveWithMosek) { + case Off: + activeConstraints = solver->satisfy(); + for (unsigned i=0;i<vars.size();i++) { + result[i]=vars[i]->finalPosition; + } + break; + case Inner: +#ifdef MOSEK_AVAILABLE + float *ba=new float[vars.size()]; + float *coords=new float[vars.size()]; + for(unsigned i=0;i<vars.size();i++) { + ba[i]=vars[i]->desiredPosition; + } + mosek_quad_solve_sep(menv,ba,coords); + for(unsigned i=0;i<vars.size();i++) { + //printf("x[%d]=%f\n",i,coords[i]); + result[i]=coords[i]; + } + delete [] ba; + delete [] coords; + break; +#endif + default: + break; + } + return activeConstraints; +} + +/* + * Use gradient-projection to solve an instance of + * the Variable Placement with Separation Constraints problem. + */ +unsigned GradientProjection::solve( + valarray<double> const &linearCoefficients, + valarray<double> &x) { + COLA_ASSERT(linearCoefficients.size()==x.size()); + COLA_ASSERT(x.size()==denseSize); + COLA_ASSERT(numStaticVars>=denseSize); + COLA_ASSERT(sparseQ==nullptr || + (sparseQ!=nullptr && (vars.size()==sparseQ->rowSize())) ); + + if(max_iterations==0) return 0; + + bool converged=false; + + solver = setupVPSC(); +#ifdef MOSEK_AVAILABLE + if(solveWithMosek==Outer) { + float* ba=new float[vars.size()]; + float* xa=new float[vars.size()]; + for(unsigned i=0;i<vars.size();i++) { + ba[i]=-linearCoefficients[i]; + } + mosek_quad_solve_sep(menv,ba,xa); + for(unsigned i=0;i<vars.size();i++) { + //printf("mosek result x[%d]=%f\n",i,xa[i]); + x[i]=xa[i]; + } + delete [] ba; + delete [] xa; + return 1; + } +#endif + // it may be that we have to consider dummy vars, which the caller didn't know + // about. Thus vars.size() may not equal x.size() + unsigned n = vars.size(); + valarray<double> b(n); + result.resize(n); + + // load desired positions into vars, note that we keep desired positions + // already calculated for dummy vars + for (unsigned i=0;i<x.size();i++) { + COLA_ASSERT(!std::isnan(x[i])); + COLA_ASSERT(std::isfinite(x[i])); + b[i]=i<linearCoefficients.size()?linearCoefficients[i]:0; + result[i]=x[i]; + if(scaling) { + b[i]*=vars[i]->scale; + result[i]/=vars[i]->scale; + } + if(!vars[i]->fixedDesiredPosition) vars[i]->desiredPosition=result[i]; + } + runSolver(result); + + valarray<double> g(n); /* gradient */ + valarray<double> previous(n); /* stored positions */ + valarray<double> d(n); /* actual descent vector */ + +#ifdef CHECK_CONVERGENCE_BY_COST + double previousCost = DBL_MAX; +#endif + unsigned counter=0; + double stepSize; + for (; counter<max_iterations&&!converged; counter++) { + previous=result; + stepSize=0; + double alpha=computeSteepestDescentVector(b,result,g); + + //printf("Iteration[%d]\n",counter); + // move to new unconstrained position + for (unsigned i=0; i<n; i++) { + // dividing by variable weight is a cheap trick to make these + // weights mean something in terms of the descent vector + double step=alpha*g[i]/vars[i]->weight; + result[i]+=step; + //printf(" after unconstrained step: x[%d]=%f\n",i,result[i]); + stepSize+=step*step; + COLA_ASSERT(!std::isnan(result[i])); + COLA_ASSERT(std::isfinite(result[i])); + if(!vars[i]->fixedDesiredPosition) vars[i]->desiredPosition=result[i]; + } + + //project to constraint boundary + bool constrainedOptimum = false; + constrainedOptimum=runSolver(result); + stepSize=0; + for (unsigned i=0;i<n;i++) { + double step = previous[i]-result[i]; + stepSize+=step*step; + } + //constrainedOptimum=false; + // beta seems, more often than not, to be >1! + if(constrainedOptimum) { + // The following step limits the step-size in the feasible + // direction + d = result - previous; + const double beta = 0.5*computeStepSize(g, d); + // beta > 1.0 takes us back outside the feasible region + // beta < 0 clearly not useful and may happen due to numerical imp. + //printf("beta=%f\n",beta); + if(beta>0&&beta<0.99999) { + stepSize=0; + for (unsigned i=0; i<n; i++) { + double step=beta*d[i]; + result[i]=previous[i]+step; + stepSize+=step*step; + } + } + } +#ifdef CHECK_CONVERGENCE_BY_COST + /* This would be the slow way to detect convergence */ + //if(counter%2) { + double cost = computeCost(b,result); + printf(" gp[%d] %.15f %.15f\n",counter,previousCost,cost); + //COLA_ASSERT(previousCost>cost); + if(fabs(previousCost - cost) < tolerance) { + converged = true; + } + previousCost = cost; + //} +#else + if(stepSize<tolerance) converged = true; +#endif + } + //printf("GP[%d] converged after %d iterations.\n",k,counter); + for(unsigned i=0;i<x.size();i++) { + x[i]=result[i]; + if(scaling) { + x[i]*=vars[i]->scale; + } + } + destroyVPSC(solver); + return counter; +} +// Setup an instance of the Variable Placement with Separation Constraints +// for one iteration. +// Generate transient local constraints --- such as non-overlap constraints +// --- that are only relevant to one iteration, and merge these with the +// global constraint list (including alignment constraints, +// dir-edge constraints, containment constraints, etc). +IncSolver* GradientProjection::setupVPSC() { + if(nonOverlapConstraints!=None) { + if(clusterHierarchy) { + //printf("Setup up cluster constraints, dim=%d--------------\n",k); + //clusterHierarchy->generateNonOverlapConstraints(k,nonOverlapConstraints,*rs,vars,lcs); + } else { + for(vector<OrthogonalEdgeConstraint*>::iterator i=orthogonalEdges.begin();i!=orthogonalEdges.end();i++) { + OrthogonalEdgeConstraint* e=*i; + e->generateTopologyConstraints(k,*rs,vars,lcs); + } + if(k==HORIZONTAL) { + // Make rectangles a little bit wider when processing horizontally so that any overlap + // resolved horizontally is strictly non-overlapping when processing vertically + Rectangle::setXBorder(0.0001); + // use rs->size() rather than n because some of the variables may + // be dummy vars with no corresponding rectangle + generateXConstraints(*rs,vars,lcs,nonOverlapConstraints==Both?true:false); + Rectangle::setXBorder(0); + } else { + generateYConstraints(*rs,vars,lcs); + } + } + } + cs=gcs; + cs.insert(cs.end(),lcs.begin(),lcs.end()); + switch(solveWithMosek) { + case Off: + break; +#ifdef MOSEK_AVAILABLE + case Inner: + menv = mosek_init_sep_ls(vars.size(),cs); + break; + case Outer: + unsigned n = vars.size(); + float* lap = new float[n*(n+1)/2]; + unsigned k=0; + for(unsigned i=0;i<n;i++) { + for(unsigned j=i;j<n;j++) { + lap[k]=(*denseQ)[i*n+j]; + k++; + } + } + menv = mosek_init_sep(lap,n,cs,1); + delete [] lap; + break; +#endif + default: + break; + } + return new IncSolver(vars,cs); +} +void GradientProjection::destroyVPSC(IncSolver *vpsc) { + if(ccs) { + for(CompoundConstraints::const_iterator c=ccs->begin(); + c!=ccs->end();++c) { + (*c)->updatePosition(vpsc::XDIM); + (*c)->updatePosition(vpsc::YDIM); + } + } + if(unsatisfiableConstraints) { + unsatisfiableConstraints->clear(); + for(Constraints::iterator i=cs.begin();i!=cs.end();i++) { + Constraint* c=*i; + if(c->unsatisfiable) { + UnsatisfiableConstraintInfo *ci = new UnsatisfiableConstraintInfo(c); + unsatisfiableConstraints->push_back(ci); + } + } + } + if(clusterHierarchy) { + clusterHierarchy->computeBoundary(*rs); + } + if(sparseQ) { + for(unsigned i=numStaticVars;i<vars.size();i++) { + delete vars[i]; + } + vars.resize(numStaticVars); + sparseQ=nullptr; + } + for(vector<Constraint*>::iterator i=lcs.begin();i!=lcs.end();i++) { + delete *i; + } + lcs.clear(); + delete vpsc; +#ifdef MOSEK_AVAILABLE + if(solveWithMosek!=Off) mosek_delete(menv); +#endif +} +void GradientProjection::straighten( + cola::SparseMatrix const * Q, + vector<SeparationConstraint*> const & cs, + vector<straightener::Node*> const & snodes) +{ + COLA_ASSERT(Q->rowSize()==snodes.size()); + COLA_ASSERT(vars.size()==numStaticVars); + sparseQ = Q; + for(unsigned i=numStaticVars;i<snodes.size();i++) { + Variable* v=new vpsc::Variable(i,snodes[i]->pos[k],1); + COLA_ASSERT(v->desiredPosition==snodes[i]->pos[k]); + vars.push_back(v); + } + COLA_ASSERT(lcs.size()==0); + for(vector<SeparationConstraint*>::const_iterator i=cs.begin();i!=cs.end();i++) { + (*i)->generateSeparationConstraints(k, vars, lcs, *rs); + } +} +} // namespace cola diff --git a/src/3rdparty/adaptagrams/libcola/gradient_projection.h b/src/3rdparty/adaptagrams/libcola/gradient_projection.h new file mode 100644 index 0000000..0e85780 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/gradient_projection.h @@ -0,0 +1,165 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef _GRADIENT_PROJECTION_H +#define _GRADIENT_PROJECTION_H + +#include <iostream> +#include <cmath> +#include <valarray> + +#include "libvpsc/solve_VPSC.h" +#include "libvpsc/variable.h" +#include "libvpsc/constraint.h" +#include "libvpsc/rectangle.h" +#include "libcola/commondefs.h" +#include "libcola/compound_constraints.h" +#include "libcola/cluster.h" +#include "libcola/sparse_matrix.h" +#ifdef MOSEK_AVAILABLE +#include "libvpsc/mosek_quad_solve.h" +#endif + +namespace straightener { + class Node; +} +namespace cola { + +enum SolveWithMosek { Off, Inner, Outer }; + +class GradientProjection { +public: + /** + * GradientProjection solves a linear system + * Qx=b + * subject to separation constraints. + * The usual use-case is with a dense square matrix (denseQ). + * However, certain CompoundConstraints and also clusters add dummy + * variables and simple goal terms which populate a sparse matrix + * sparseQ (constructed in this constructor). + * A motivated person could rewrite the constructor to allow + * arbitrary sparse terms (if they had a use for it). + */ + GradientProjection( + const vpsc::Dim k, + std::valarray<double> *denseQ, + const double tol, + const unsigned max_iterations, + CompoundConstraints const *ccs, + UnsatisfiableConstraintInfos *unsatisfiableConstraints, + NonOverlapConstraintsMode nonOverlapConstraints = None, + RootCluster* clusterHierarchy = nullptr, + vpsc::Rectangles* rs = nullptr, + const bool scaling = false, + SolveWithMosek solveWithMosek = Off); + static void dumpSquareMatrix(std::valarray<double> const &L) { + unsigned n=static_cast<unsigned>(floor(sqrt(static_cast<double>(L.size())))); + printf("Matrix %dX%d\n{",n,n); + for(unsigned i=0;i<n;i++) { + printf("{"); + for(unsigned j=0;j<n;j++) { + char c=j==n-1?'}':','; + printf("%f%c",1. * L[i*n+j],c); + } + char c=i==n-1?'}':','; + printf("%c\n",c); + } + } + + unsigned getNumStaticVars() const { + return numStaticVars; + } + ~GradientProjection() { + //destroyVPSC(solver); + for(vpsc::Constraints::iterator i(gcs.begin()); i!=gcs.end(); i++) { + delete *i; + } + gcs.clear(); + for(unsigned i=0;i<vars.size();i++) { + delete vars[i]; + } + } + unsigned solve(std::valarray<double> const & b, std::valarray<double> & x); + void unfixPos(unsigned i) { + if(vars[i]->fixedDesiredPosition) { + vars[i]->weight=1; + vars[i]->fixedDesiredPosition=false; + } + } + void fixPos(const unsigned i,const double pos) { + vars[i]->weight=100000.; + vars[i]->desiredPosition=pos; + vars[i]->fixedDesiredPosition=true; + } + vpsc::Dim getDimension() const { + return k; + } + void straighten( + cola::SparseMatrix const * Q, + std::vector<SeparationConstraint*> const & ccs, + std::vector<straightener::Node*> const & snodes); + std::valarray<double> const & getFullResult() const { + return result; + } +private: + vpsc::IncSolver* setupVPSC(); + double computeCost(std::valarray<double> const &b, + std::valarray<double> const &x) const; + double computeSteepestDescentVector( + std::valarray<double> const &b, std::valarray<double> const &place, + std::valarray<double> &g) const; + double computeScaledSteepestDescentVector( + std::valarray<double> const &b, std::valarray<double> const &place, + std::valarray<double> &g) const; + double computeStepSize( + std::valarray<double> const & g, std::valarray<double> const & d) const; + bool runSolver(std::valarray<double> & result); + void destroyVPSC(vpsc::IncSolver *vpsc); + vpsc::Dim k; + unsigned numStaticVars; // number of variables that persist + // throughout iterations + const unsigned denseSize; // denseQ has denseSize^2 entries + std::valarray<double> *denseQ; // dense square graph laplacian matrix + std::valarray<double> scaledDenseQ; // scaled dense square graph laplacian matrix + std::vector<vpsc::Rectangle*>* rs; + CompoundConstraints const *ccs; + UnsatisfiableConstraintInfos *unsatisfiableConstraints; + NonOverlapConstraintsMode nonOverlapConstraints; + Cluster* clusterHierarchy; + double tolerance; + unsigned max_iterations; + cola::SparseMatrix const * sparseQ; // sparse components of goal function + vpsc::Variables vars; // all variables + // computations + vpsc::Constraints gcs; /* global constraints - persist throughout all + iterations */ + vpsc::Constraints lcs; /* local constraints - only for current iteration */ + vpsc::Constraints cs; /* working list of constraints: gcs +lcs */ + std::valarray<double> result; +#ifdef MOSEK_AVAILABLE + MosekEnv* menv; +#endif + vpsc::IncSolver* solver; + SolveWithMosek solveWithMosek; + const bool scaling; + std::vector<OrthogonalEdgeConstraint*> orthogonalEdges; +}; +} // namespace cola +#endif /* _GRADIENT_PROJECTION_H */ diff --git a/src/3rdparty/adaptagrams/libcola/libcola.pc.in b/src/3rdparty/adaptagrams/libcola/libcola.pc.in new file mode 100644 index 0000000..f9d0688 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/libcola.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libcola +Description: A library for constraint graph layout +URL: http://www.adaptagrams.org/ +Version: @VERSION@ +Libs: -L${libdir} -lcola +Cflags: -I${includedir}/libcola diff --git a/src/3rdparty/adaptagrams/libcola/output_svg.cpp b/src/3rdparty/adaptagrams/libcola/output_svg.cpp new file mode 100644 index 0000000..cd564e6 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/output_svg.cpp @@ -0,0 +1,389 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#include <string> +#include <iostream> +#include <sstream> +#include <list> + +#include "libcola/output_svg.h" +#include "libcola/cola.h" +#include "libcola/straightener.h" + +using namespace cola; +using vpsc::Rectangle; +using std::endl; +using std::cout; +using std::ios; +using std::max; +using std::min; +using std::ofstream; +using std::vector; +using std::list; + +void OutputFile::generate() { + unsigned E=es.size(); + bool cleanupRoutes=false; + if(routes==nullptr) { + cleanupRoutes=true; + routes = new vector<straightener::Route*>(E); + for(unsigned i=0;i<E;i++) { + straightener::Route* r=new straightener::Route(2); + r->xs[0]=rs[es[i].first]->getCentreX(); + r->ys[0]=rs[es[i].first]->getCentreY(); + r->xs[1]=rs[es[i].second]->getCentreX(); + r->ys[1]=rs[es[i].second]->getCentreY(); + (*routes)[i]=r; + } + } + +#if defined (CAIRO_HAS_SVG_SURFACE) && defined (CAIRO_HAS_PDF_SURFACE) + double width,height,r=2; + if(rects) r=rs[0]->width()/2; + double xmin=DBL_MAX, ymin=xmin; + double xmax=-DBL_MAX, ymax=xmax; + for (unsigned i=0;i<rs.size();i++) { + double x=rs[i]->getCentreX(), y=rs[i]->getCentreY(); + xmin=min(xmin,x); + ymin=min(ymin,y); + xmax=max(xmax,x); + ymax=max(ymax,y); + } + xmax+=2*r; + ymax+=2*r; + xmin-=2*r; + ymin-=2*r; + width=xmax-xmin; + height=ymax-ymin; + + Cairo::RefPtr<Cairo::Context> cr; + openCairo(cr,width,height); + + /* set background colour + cr->save(); // save the state of the context + cr->set_source_rgb(0.86, 0.85, 0.47); + cr->paint(); // fill image with the color + cr->restore(); // color is back to black now + */ + + cr->set_line_width(1.); + cr->set_font_size(8); + cr->save(); + if(rc) for(Clusters::const_iterator c=rc->clusters.begin();c!=rc->clusters.end();c++) { + draw_cluster_boundary(cr,**c,xmin,ymin); + } + if(curvedEdges) + draw_curved_edges(cr,es,xmin,ymin); + else + draw_edges(cr,*routes,xmin,ymin); + Cairo::TextExtents te; + for (unsigned i=0;i<rs.size();i++) { + if(!rects) { + double x=rs[i]->getCentreX()-xmin, y=rs[i]->getCentreY()-ymin; + cr->arc(x,y,r, 0.0, 2.0 * M_PI); + cr->fill(); + } else { + double x=rs[i]->getMinX()-xmin+0.5, y=rs[i]->getMinY()-ymin+0.5; + std::string str; + if(labels.size()==rs.size()) { + str=labels[i]; + } else { + std::stringstream s; s<<i; + str=s.str(); + } + cr->get_text_extents(str,te); + /* + double llx = x-te.width/2.-1; + double lly = y-te.height/2.-1; + cr->rectangle(llx,lly,te.width+2,te.height+2); + */ + cr->rectangle(x,y, + rs[i]->width()-1,rs[i]->height()-1); + cr->stroke_preserve(); + cr->save(); + cr->set_source_rgba(245./255., 233./255., 177./255., 0.6); + cr->fill(); + cr->restore(); + if(labels.size()==rs.size()) { + cr->move_to(x-te.x_bearing+te.width/2.,y-te.y_bearing+te.height/2.); + cr->show_text(str); + } + cr->stroke(); + } + } + + cr->show_page(); + + std::cout << "Wrote file \"" << fname << "\"" << std::endl; + +#else + std::cout << + "WARNING: cola::OutputFile::generate(): No SVG file produced." << + std::endl << + " You must have cairomm (and cairo with SVG support) " << + "this to work." << std::endl; +#endif + + if(cleanupRoutes) { + for(unsigned i=0;i<E;i++) { + delete (*routes)[i]; + } + delete routes; + } +} + +#ifdef HAVE_CAIROMM +void OutputFile::draw_cluster_boundary(Cairo::RefPtr<Cairo::Context> const &cr, + Cluster &c, + const double xmin, + const double ymin) { + c.computeBoundary(rs); + cr->save(); + // background + cr->set_source_rgb(0.7, 0.7, 224./255.); + cr->move_to(c.hullX[0]-xmin,c.hullY[0]-ymin); + for(unsigned i=1;i<c.hullX.size();i++) { + cr->line_to(c.hullX[i]-xmin,c.hullY[i]-ymin); + } + cr->line_to(c.hullX[0]-xmin,c.hullY[0]-ymin); + cr->fill(); + cr->restore(); + // outline + cr->move_to(c.hullX[0]-xmin,c.hullY[0]-ymin); + for(unsigned i=1;i<c.hullX.size();i++) { + cr->line_to(c.hullX[i]-xmin,c.hullY[i]-ymin); + } + cr->line_to(c.hullX[0]-xmin,c.hullY[0]-ymin); + cr->stroke(); +} + +void OutputFile::draw_edges(Cairo::RefPtr<Cairo::Context> &cr, + vector<straightener::Route*> const & es, double const xmin, double const ymin) { + cr->save(); + // background + cr->set_source_rgba(0,0,1,0.5); + for (unsigned i=0;i<es.size();i++) { + const straightener::Route* r=es[i]; + cr->move_to(r->xs[0]-xmin,r->ys[0]-ymin); + for (unsigned j=1;j<r->n;j++) { + cr->line_to(r->xs[j]-xmin,r->ys[j]-ymin); + } + cr->stroke(); + } + cr->restore(); +} + +namespace bundles { +struct CEdge { + unsigned startID, endID; + double x0,y0,x1,y1,x2,y2,x3,y3; +}; +struct CBundle; +struct CNode { + double x,y; + vector<CEdge*> edges; + list<CBundle*> bundles; +}; +double vangle(double ax,double ay, double bx, double by) { + double ab=ax*bx+ay*by; + double len=sqrt(ax*ax+ay*ay)*sqrt(bx*bx+by*by); + double angle=acos(ab/len); + //printf("ab=%f len=%f angle=%f\n",ab,len,angle); + return angle; +} +struct CBundle { + unsigned w; + double x0, y0; + double sx,sy; + vector<CEdge*> edges; + CBundle(CNode const &u) : w(u.edges.size()), x0(u.x), y0(u.y), sx(w*u.x), sy(w*u.y) { } + void addEdge(CEdge *e) { + if(x0==e->x0 && y0==e->y0) { + sx+=e->x3; sy+=e->y3; + } else { + sx+=e->x0; sy+=e->y0; + } + edges.push_back(e); + } + double x1() const { + return sx/(w+edges.size()); + } + double y1() const { + return sy/(w+edges.size()); + } + double angle(CBundle* const &b) const { + double ax=x1()-x0; + double ay=y1()-y0; + double bx=b->x1()-b->x0; + double by=b->y1()-b->y0; + return vangle(ax,ay,bx,by); + } + double yangle() const { + double x=x1()-x0; + double y=y1()-y0; + double o=x<0?1:-1; + return vangle(0,1,x,y)*o+M_PI; + } + void merge(CBundle* b) { + for(unsigned i=0;i<b->edges.size();i++) { + addEdge(b->edges[i]); + } + } + void dump() { + printf("Bundle: "); + for(unsigned i=0;i<edges.size();i++) { + printf("(%d,%d) ",edges[i]->startID,edges[i]->endID); + } + } +}; +struct clockwise { + bool operator() (CBundle* const &a, CBundle* const &b) { + return a->yangle()<b->yangle(); + } +}; +} //namespace bundles + +/* + * draw edges bundled. That is, edges are drawn as splines, with the control points + * between adjacent edges outgoing from a particular node shared if the angle between them + * is less than pi/8 + */ +void OutputFile::draw_curved_edges(Cairo::RefPtr<Cairo::Context> &cr, + vector<cola::Edge> const & es, + const double xmin, + const double ymin) { + using namespace bundles; + vector<CNode> nodes(rs.size()); + vector<CEdge> edges(es.size()); + for (unsigned i=0;i<es.size();i++) { + CEdge *e=&edges[i]; + unsigned start=es[i].first; + unsigned end=es[i].second; + e->startID=start; + e->endID=end; + nodes[start].x=rs[start]->getCentreX()-xmin; + nodes[start].y=rs[start]->getCentreY()-ymin; + nodes[end].x=rs[end]->getCentreX()-xmin; + nodes[end].y=rs[end]->getCentreY()-ymin; + e->x0=nodes[start].x; + e->x1=nodes[start].x; + e->x2=nodes[end].x; + e->x3=nodes[end].x; + e->y0=nodes[start].y; + e->y1=nodes[start].y; + e->y2=nodes[end].y; + e->y3=nodes[end].y; + nodes[end].edges.push_back(e); + nodes[start].edges.push_back(e); + } + + for (unsigned i=0;i<nodes.size();i++) { + CNode u=nodes[i]; + if(u.edges.size()<2) continue; + for (unsigned j=0;j<u.edges.size();j++) { + CBundle* b=new CBundle(u); + b->addEdge(u.edges[j]); + u.bundles.push_back(b); + } + u.bundles.sort(clockwise()); + /* + printf("Sorted: \n"); + list<CBundle*>::iterator i,j; + for(list<CBundle*>::iterator i=u.bundles.begin();i!=u.bundles.end();i++) { + CBundle* a=*i; + a->dump(); + printf(" angle=%f\n",a->yangle()); + } + printf("---------\n"); + */ + while(true) { + double minAngle=DBL_MAX; + list<CBundle*>::iterator mini,minj,i,j; + for(i=u.bundles.begin();i!=u.bundles.end();i++) { + j=i; + if(++j==u.bundles.end()) { + j=u.bundles.begin(); + } + CBundle* a=*i; + CBundle* b=*j; + double angle=b->yangle()-a->yangle(); + if(angle<0) angle+=2*M_PI; + //printf("between "); + //a->dump(); b->dump(); + //printf(" angle=%f\n",angle); + if(angle<minAngle) { + minAngle=angle; + mini=i; + minj=j; + } + } + if(minAngle>cos(M_PI/8.)) break; + CBundle* a=*mini; + CBundle* b=*minj; + //a->dump(); + //b->dump(); + b->merge(a); + //printf("***Merged on %f***: ",minAngle); + //b->dump(); + //printf("\n"); + u.bundles.erase(mini); + if(u.bundles.size() < 2) break; + } + for(list<CBundle*>::iterator i=u.bundles.begin();i!=u.bundles.end();i++) { + CBundle* b=*i; + for(unsigned i=0;i<b->edges.size();i++) { + CEdge* e=b->edges[i]; + if(e->x0==u.x&&e->y0==u.y) { + e->x1=b->x1(); + e->y1=b->y1(); + } else { + e->x2=b->x1(); + e->y2=b->y1(); + } + } + } + } + + cr->save(); + // background + cr->set_source_rgba(0,0,1,0.2); + for (unsigned i=0;i<edges.size();i++) { + CEdge &e=edges[i]; + cr->move_to(e.x0,e.y0); + cr->curve_to(e.x1,e.y1,e.x2,e.y2,e.x3,e.y3); + cr->stroke(); + } + cr->restore(); +} +void OutputFile::openCairo(Cairo::RefPtr<Cairo::Context> &cr, double width, double height) { + if(fname.rfind("pdf") == (fname.length()-3) ) { + printf("writing pdf file: %s\n",fname.c_str()); + Cairo::RefPtr<Cairo::PdfSurface> pdfsurface = + Cairo::PdfSurface::create(fname, width, height); + cr = Cairo::Context::create(pdfsurface); + } else { + printf("writing svg file: %s\n",fname.c_str()); + Cairo::RefPtr<Cairo::SvgSurface> svgsurface = + Cairo::SvgSurface::create(fname, width, height); + cr = Cairo::Context::create(svgsurface); + } +} + +#endif // HAVE_CAIROMM diff --git a/src/3rdparty/adaptagrams/libcola/output_svg.h b/src/3rdparty/adaptagrams/libcola/output_svg.h new file mode 100644 index 0000000..d68f161 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/output_svg.h @@ -0,0 +1,80 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef _OUTPUT_SVG_H +#define _OUTPUT_SVG_H + +#include "libcola/config.h" +#include "libcola/cola.h" + +#ifdef HAVE_CAIROMM +#include <cairomm/context.h> +#include <cairomm/surface.h> +#endif + +class OutputFile { +public: + std::vector<vpsc::Rectangle*> const &rs; + std::vector<cola::Edge> const &es; + std::vector<straightener::Route*> *routes; + cola::RootCluster const * rc; + std::string const fname; + bool rects; + bool curvedEdges; + OutputFile(std::vector<vpsc::Rectangle*> const &rs, + std::vector<cola::Edge> const &es, + cola::RootCluster const * rc, + std::string const fname, + const bool rects=false, + const bool curvedEdges=false) + : rs(rs), + es(es), + routes(nullptr), + rc(rc), + fname(fname), + rects(rects), + curvedEdges(curvedEdges) {} + void generate(); + void setLabels(std::vector<std::string> ls) { + labels.resize(ls.size()); + std::copy(ls.begin(),ls.end(),labels.begin()); + } + void setLabels(const unsigned n, const char **ls) { + labels.resize(n); + for(unsigned i=0;i<n;i++) { + labels[i]=ls[i]; + } + } +private: +#ifdef HAVE_CAIROMM + void draw_cluster_boundary(Cairo::RefPtr<Cairo::Context> const &cr, + cola::Cluster &c, const double xmin, const double ymin); + void draw_edges(Cairo::RefPtr<Cairo::Context> &cr, + std::vector<straightener::Route*> const & es, + double const xmin, double const ymin); + void draw_curved_edges(Cairo::RefPtr<Cairo::Context> &cr, + std::vector<cola::Edge> const & es, + const double xmin, + const double ymin); + void openCairo(Cairo::RefPtr<Cairo::Context> &cr, double width, double height); +#endif // HAVE_CAIROMM + std::vector<std::string> labels; +}; +#endif // _OUTPUT_SVG_H diff --git a/src/3rdparty/adaptagrams/libcola/pseudorandom.cpp b/src/3rdparty/adaptagrams/libcola/pseudorandom.cpp new file mode 100644 index 0000000..6577b3a --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/pseudorandom.cpp @@ -0,0 +1,48 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2015 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer +*/ + +#include "libcola/pseudorandom.h" + +namespace cola { + +PseudoRandom::PseudoRandom(double s) + : a(214013), + c(2531011), + m(2147483648), + range(32767), + seed(s) +{ +} + +double PseudoRandom::getNext(void) +{ + seed = (seed * a + c) % m; + return (seed >> 16) / range; +} + +double PseudoRandom::getNextBetween(double min, double max) +{ + return min + getNext() * (max - min); +} + + +} + diff --git a/src/3rdparty/adaptagrams/libcola/pseudorandom.h b/src/3rdparty/adaptagrams/libcola/pseudorandom.h new file mode 100644 index 0000000..bb3b269 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/pseudorandom.h @@ -0,0 +1,44 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2015 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer +*/ + +#ifndef COLA_PSEUDORANDOM_H +#define COLA_PSEUDORANDOM_H + +namespace cola { + +class PseudoRandom +{ +public: + PseudoRandom(double s = 1); + + double getNext(void); + double getNextBetween(double min, double max); + +private: + int a; + int c; + unsigned int m; + double range; + unsigned int seed; +}; + +} +#endif // COLA_PSEUDORANDOM_H diff --git a/src/3rdparty/adaptagrams/libcola/shapepair.cpp b/src/3rdparty/adaptagrams/libcola/shapepair.cpp new file mode 100644 index 0000000..5673322 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/shapepair.cpp @@ -0,0 +1,47 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#include "libvpsc/assertions.h" + +#include "libcola/shapepair.h" + +namespace cola { + +ShapePair::ShapePair(unsigned ind1, unsigned ind2) +{ + COLA_ASSERT(ind1 != ind2); + // Assign the lesser value to m_index1. + m_index1 = (ind1 < ind2) ? ind1 : ind2; + // Assign the greater value to m_index2. + m_index2 = (ind1 > ind2) ? ind1 : ind2; +} + +bool ShapePair::operator<(const ShapePair& rhs) const +{ + if (m_index1 != rhs.m_index1) + { + return m_index1 < rhs.m_index1; + } + return m_index2 < rhs.m_index2; +} + +}; diff --git a/src/3rdparty/adaptagrams/libcola/shapepair.h b/src/3rdparty/adaptagrams/libcola/shapepair.h new file mode 100644 index 0000000..7c122cb --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/shapepair.h @@ -0,0 +1,49 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Michael Wybrow + * +*/ + +#ifndef COLA_SHAPEPAIR_H +#define COLA_SHAPEPAIR_H + +namespace cola { + +// A pair of indexes. +// Specified unordered but stored ordered so it can be compared and +// stored in a set. +// +class ShapePair +{ + public: + ShapePair(unsigned ind1, unsigned ind2); + bool operator<(const ShapePair& rhs) const; + unsigned short index1(void) const {return m_index1;} + unsigned short index2(void) const {return m_index2;} + + private: + unsigned short m_index1; + unsigned short m_index2; +}; + + +}; + +#endif + diff --git a/src/3rdparty/adaptagrams/libcola/shortest_paths.h b/src/3rdparty/adaptagrams/libcola/shortest_paths.h new file mode 100644 index 0000000..22b54e3 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/shortest_paths.h @@ -0,0 +1,245 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2014 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer +*/ + +#ifndef SHORTEST_PATHS_H +#define SHORTEST_PATHS_H + +#include <vector> +#include <valarray> +#include <cfloat> +#include <cassert> +#include <algorithm> +#include <iostream> +#include <limits> + +#include "libcola/commondefs.h" +#include <libvpsc/pairing_heap.h> +#include <libvpsc/assertions.h> + +template <class T> +struct PairNode; + +namespace shortest_paths { + +template <typename T> +struct Node { + unsigned id; + T d; + Node* p; // predecessor + std::vector<Node<T>*> neighbours; + std::vector<T> nweights; + PairNode<Node<T>*>* qnode; +}; +template <typename T> +struct CompareNodes { + bool operator() (Node<T> *const &u, Node<T> *const &v) const { + if(u==v) return false; // with g++ 4.1.2 unless I have this explicit check + // it returns true for this case when using -O3 optimization + // CRAZY! + if(u->d < v->d) { + return true; + } + return false; + } +}; + +typedef std::pair<unsigned,unsigned> Edge; +template <typename T> +/** + * returns the adjacency matrix, 0 entries for non-adjacent nodes + * @param n total number of nodes + * @param D n*n matrix of shortest paths + * @param es edge pairs + * @param eweights edge weights, if empty then all weights will be taken as 1 + */ +void neighbours(unsigned const n, T** D, std::vector<Edge> const & es, + std::valarray<T> const & eweights = std::valarray<T>()); +/** + * find all pairs shortest paths, n^3 dynamic programming approach + * @param n total number of nodes + * @param D n*n matrix of shortest paths + * @param es edge pairs + * @param eweights edge weights, if empty then all weights will be taken as 1 + */ +template <typename T> +void floyd_warshall(unsigned const n, T** D, std::vector<Edge> const & es, + std::valarray<T> const & eweights = std::valarray<T>()); + +/** + * find all pairs shortest paths, faster, uses dijkstra + * @param n total number of nodes + * @param D n*n matrix of shortest paths + * @param es edge pairs + * @param eweights edge weights, if empty then all weights will be taken as 1 + */ +template <typename T> +void johnsons(unsigned const n, T** D, std::vector<Edge> const & es, + std::valarray<T> const & eweights = std::valarray<T>()); +/** + * find shortest path lengths from node s to all other nodes + * @param s starting node + * @param n total number of nodes + * @param d n vector of path lengths + * @param es edge pairs + * @param eweights edge weights, if empty then all weights will be taken as 1 + */ +template <typename T> +void dijkstra(unsigned const s, unsigned const n, T* d, + std::vector<Edge> const & es, + std::valarray<T> const & eweights = std::valarray<T>()); + + +//----------------------------------------------------------------------------- +// Implementation: + +// O(n^3) time dynamic programming approach. Slow, but fool proof. +// Use for testing. +template <typename T> +void floyd_warshall( + unsigned const n, + T** D, + std::vector<Edge> const & es, + std::valarray<T> const & eweights) +{ + COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); + for(unsigned i=0;i<n;i++) { + for(unsigned j=0;j<n;j++) { + if(i==j) D[i][j]=0; + else D[i][j]=std::numeric_limits<T>::max(); + } + } + for(unsigned i=0;i<es.size();i++) { + unsigned u=es[i].first, v=es[i].second; + COLA_ASSERT(u<n&&v<n); + D[u][v] = D[v][u] = (eweights.size() > 0) ? eweights[i] : 1; + } + for(unsigned k=0; k<n; k++) { + for(unsigned i=0; i<n; i++) { + for(unsigned j=0; j<n; j++) { + D[i][j]=std::min(D[i][j],D[i][k]+D[k][j]); + } + } + } +} +// Simply returns the adjacency graph +template <typename T> +void neighbours( + unsigned const n, + T** D, + std::vector<Edge> const & es, + std::valarray<T> const & eweights) +{ + COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); + for(unsigned i=0;i<n;i++) { + for(unsigned j=0;j<n;j++) { + D[i][j]=0; + } + } + for(unsigned i=0;i<es.size();i++) { + unsigned u=es[i].first, v=es[i].second; + COLA_ASSERT(u<n&&v<n); + D[u][v] = D[v][u] = (eweights.size() > 0) ? eweights[i] : 1; + } +} +template <typename T> +void dijkstra_init( + std::vector<Node<T> > & vs, + std::vector<Edge> const& es, + std::valarray<T> const & eweights) { + COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); +#ifndef NDEBUG + const unsigned n=vs.size(); +#endif + for(unsigned i=0;i<es.size();i++) { + unsigned u=es[i].first, v=es[i].second; + COLA_ASSERT(u<n); + COLA_ASSERT(v<n); + T w = (eweights.size() > 0) ? eweights[i] : 1; + vs[u].neighbours.push_back(&vs[v]); + vs[u].nweights.push_back(w); + vs[v].neighbours.push_back(&vs[u]); + vs[v].nweights.push_back(w); + } +} +template <typename T> +void dijkstra( + unsigned const s, + std::vector<Node<T> > & vs, + T* d) +{ + const unsigned n=vs.size(); + COLA_ASSERT(s<n); + for(unsigned i=0;i<n;i++) { + vs[i].id=i; + vs[i].d=std::numeric_limits<T>::max(); + vs[i].p=nullptr; + } + vs[s].d=0; + PairingHeap<Node<T>*,CompareNodes<T> > Q; + for(unsigned i=0;i<n;i++) { + vs[i].qnode = Q.insert(&vs[i]); + } + while(!Q.isEmpty()) { + Node<T> *u=Q.extractMin(); + d[u->id]=u->d; + for(unsigned i=0;i<u->neighbours.size();i++) { + Node<T> *v=u->neighbours[i]; + T w=u->nweights[i]; + if(u->d!=std::numeric_limits<T>::max() + && v->d > u->d+w) { + v->p=u; + v->d=u->d+w; + Q.decreaseKey(v->qnode,v); + } + } + } +} +template <typename T> +void dijkstra( + unsigned const s, + unsigned const n, + T* d, + std::vector<Edge> const & es, + std::valarray<T> const & eweights) +{ + COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); + COLA_ASSERT(s<n); + std::vector<Node<T> > vs(n); + dijkstra_init(vs,es,eweights); + dijkstra(s,vs,d); +} + +template <typename T> +void johnsons( + unsigned const n, + T** D, + std::vector<Edge> const & es, + std::valarray<T> const & eweights) +{ + std::vector<Node<T> > vs(n); + dijkstra_init(vs,es,eweights); + for(unsigned k=0;k<n;k++) { + dijkstra(k,vs,D[k]); + } +} + +} //namespace shortest_paths +#endif //SHORTEST_PATHS_H diff --git a/src/3rdparty/adaptagrams/libcola/sparse_matrix.h b/src/3rdparty/adaptagrams/libcola/sparse_matrix.h new file mode 100644 index 0000000..f4ec858 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/sparse_matrix.h @@ -0,0 +1,140 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer +*/ + +/* + * Yale Sparse Matrix implementation (from Wikipedia definition). + * It stores an initial sparse n×n matrix M in row form using three arrays, A, + * IA, JA. NZ denotes the number of nonzero entries in matrix M. The array A + * then is of length NZ and holds all nonzero entries of M. The array IA stores + * at IA(i) the position of the first element of row i in the sparse array A. + * The length of row i is determined by IA(i+1) - IA(i). Therefore IA needs to + * be of length N + 1. In array JA, the column index of the element A(j) is + * stored. JA is of length NZ. + */ +#ifndef _SPARSE_MATRIX_H +#define _SPARSE_MATRIX_H + +#include <valarray> +#include <map> +#include <cstdio> + +#include "libvpsc/assertions.h" + +namespace cola { +struct SparseMap { + SparseMap(unsigned n = 0) : n(n) {}; + unsigned n; + typedef std::pair<unsigned, unsigned> SparseIndex; + typedef std::map<SparseIndex,double> SparseLookup; + typedef SparseLookup::const_iterator ConstIt; + SparseLookup lookup; + double& operator[](const SparseIndex& k) { + return lookup[k]; + } + double& operator()(const unsigned i, const unsigned j) { + return lookup[std::make_pair(i,j)]; + } + double getIJ(const unsigned i, const unsigned j) const { + COLA_ASSERT(i<n); + COLA_ASSERT(j<n); + ConstIt v=lookup.find(std::make_pair(i,j)); + if(v!=lookup.end()) { + return v->second; + } + return 0; + } + size_t nonZeroCount() const { + return lookup.size(); + } + void resize(unsigned n) { + this->n = n; + } + void clear() { + lookup.clear(); + } +}; +/* + * Yale Sparse Matrix implementation (from Wikipedia definition). + * It stores an initial sparse n×n matrix M in row form using three arrays, A, + * IA, JA. NZ denotes the number of nonzero entries in matrix M. The array A + * then is of length NZ and holds all nonzero entries of M. The array IA stores + * at IA(i) the position of the first element of row i in the sparse array A. + * The length of row i is determined by IA(i+1) - IA(i). Therefore IA needs to + * be of length N + 1. In array JA, the column index of the element A(j) is + * stored. JA is of length NZ. + */ +class SparseMatrix { +public: + SparseMatrix(SparseMap const & m) + : n(m.n), NZ((unsigned)m.nonZeroCount()), sparseMap(m), + A(std::valarray<double>(NZ)), IA(std::valarray<unsigned>(n+1)), JA(std::valarray<unsigned>(NZ)) { + unsigned cnt=0; + int lastrow=-1; + for(SparseMap::ConstIt i=m.lookup.begin(); i!=m.lookup.end(); i++) { + SparseMap::SparseIndex p = i->first; + COLA_ASSERT(p.first<n); + COLA_ASSERT(p.second<n); + A[cnt]=i->second; + if((int)p.first!=lastrow) { + for(unsigned r=lastrow+1;r<=p.first;r++) { + IA[r]=cnt; + } + lastrow=p.first; + } + JA[cnt]=p.second; + cnt++; + } + for(unsigned r=lastrow+1;r<=n;r++) { + IA[r]=NZ; + } + } + void rightMultiply(std::valarray<double> const & v, std::valarray<double> & r) const { + COLA_ASSERT(v.size()>=n); + COLA_ASSERT(r.size()>=n); + for(unsigned i=0;i<n;i++) { + r[i]=0; + for(unsigned j=IA[i];j<IA[i+1];j++) { + r[i]+=A[j]*v[JA[j]]; + } + } + } + double getIJ(const unsigned i, const unsigned j) const { + return sparseMap.getIJ(i,j); + } + void print() const { + for(unsigned i=0;i<n;i++) { + for(unsigned j=0;j<n;j++) { + printf("%f ",getIJ(i,j)); + } + printf("\n"); + } + } + unsigned rowSize() const { + return n; + } +private: + const unsigned n,NZ; + SparseMap const & sparseMap; + std::valarray<double> A; + std::valarray<unsigned> IA, JA; +}; +} //namespace cola +#endif /* _SPARSE_MATRIX_H */ diff --git a/src/3rdparty/adaptagrams/libcola/straightener.cpp b/src/3rdparty/adaptagrams/libcola/straightener.cpp new file mode 100644 index 0000000..dc22d18 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/straightener.cpp @@ -0,0 +1,798 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2005-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Author(s): Tim Dwyer + * +*/ + +/* + * Functions to automatically generate constraints for the + * rectangular node overlap removal problem. + */ + +#include <set> +#include <list> +#include <cassert> +#include <iostream> +#include <cmath> + +#include "libvpsc/assertions.h" +#include "libcola/commondefs.h" +#include "libcola/cola.h" +#include "libcola/compound_constraints.h" +#include "libcola/straightener.h" + +//#define STRAIGHTENER_DEBUG 1 + +using std::list; +using std::make_pair; +using std::pair; +using std::set; +using std::vector; +using std::copy; + +namespace straightener { + + // is point p on line a-b? + static bool pointOnLine(double px,double py, double ax, double ay, double bx, double by, double& tx) { + double dx=bx-ax; + double dy=by-ay; + double ty=0; + if(fabs(dx)<0.0001&&fabs(dy)<0.0001) { + // runty line! + tx=px-ax; + ty=py-ay; + } else { + if(fabs(dx)<0.0001) { + //vertical line + if(fabs(px-ax)<0.01) { + tx=(py-ay)/dy; + } + } else { + tx=(px-ax)/dx; + } + if(fabs(dy)<0.0001) { + //horizontal line + if(fabs(py-ay)<0.01) { + ty=tx; + } + } else { + ty=(py-ay)/dy; + } + } + //printf(" tx=%f,ty=%f\n",tx,ty); + if(fabs(tx-ty)<0.001 && tx>=0 && tx<=1) { + return true; + } + return false; + } + void Route::rerouteAround(vpsc::Rectangle* rect) { + // the first and last points should not be inside this + // rectangle - note that we should not be routing around + // rectangles directly connected to this route + COLA_ASSERT(!rect->inside(xs[0],ys[0])); + COLA_ASSERT(!rect->inside(xs[n-1],ys[n-1])); + // first, we examine each point and if it is inside the rectangle, we + // project to the nearest edge of the rectangle + for(unsigned i=1;i<n-1;i++) { + double &x=xs[i], &y=ys[i]; + if(rect->inside(x,y)) { + enum ProjectSide {LEFT, BOTTOM, RIGHT, TOP}; + unsigned projectSide = LEFT; + double minDist = x - rect->getMinX(); + double dist = y - rect->getMinY(); + if(dist<minDist) { + projectSide = BOTTOM; + minDist = dist; + } + dist = rect->getMaxX() - x; + if(dist<minDist) { + projectSide = RIGHT; + minDist = dist; + } + dist = rect->getMaxY() - y; + if(dist<minDist) { + projectSide = TOP; + minDist = dist; + } + switch(projectSide) { + case LEFT: + x=rect->getMinX(); + break; + case BOTTOM: + y=rect->getMinY(); + break; + case RIGHT: + x=rect->getMaxX(); + break; + case TOP: + y=rect->getMaxY(); + break; + } + + } + } + // the new route is copied into rxs, rys. + vector<double> rxs, rys; + double prevX=xs[0], prevY=ys[0]; + rxs.push_back(prevX); + rys.push_back(prevY); + + // check each segment in turn to see if it intersects + // with the rectangle. + // If an intersecting segment is found: + // 1) the segment passes right through the rectangle + // - we insert new segments routed around the rectangle + // 2) the segment terminates inside the rectangle + // - we follow connected segments until we find the exit + // point, then we insert a route around the rectangle + // 3) the segment just touches one side + // + for(unsigned i=1;i<n;i++) { + // we have projected all points to the boundary already so we shouldn't find any inside + COLA_ASSERT(!rect->inside(xs[i],ys[i])); + vpsc::RectangleIntersections ri; + rect->lineIntersections(prevX,prevY, + xs[i],ys[i],ri); + if(ri.intersects) { + int count=ri.countIntersections(); + COLA_ASSERT(count>0); // can't be 0 because we have detected an intersection + COLA_ASSERT(count<4); // assumes no zero width or height rects which would be + // the only way for a line segment to touch all 4 sides at once + if(count==3) { // runs along one side + COLA_ASSERT(!rect->inside(xs[i],ys[i])); + } else if(count==2) { // passes right through + COLA_ASSERT(!rect->inside(xs[i],ys[i])); + double x1=0, y1=0, x2=0, y2=0; + ri.nearest(prevX, prevY, x1, y1); + ri.nearest(xs[i], ys[i], x2, y2); + rect->routeAround(x1, y1, x2, y2, rxs, rys); + } else if(count==1) { + // single intersection, earlier projection step ensures it is on the + // perimeter, so nothing to do + } + } + prevX=xs[i]; + prevY=ys[i]; + COLA_ASSERT(!rect->inside(prevX,prevY)); + rxs.push_back(prevX); + rys.push_back(prevY); + } + delete [] xs; + delete [] ys; + n=rxs.size(); + COLA_ASSERT(rys.size()==n); + xs = new double[n]; + ys = new double[n]; + copy(rxs.begin(),rxs.end(),xs); + copy(rys.begin(),rys.end(),ys); + } + /** + * sets up the path information for an edge, + * i.e. nodes are added to the path list in the order they appear on the + * edge, from startNode to endNode. + * activePath contains at least the first and last node in the edge. + * If allActive is true then + * activePath list is also set up with a subset of nodes from path, each of + * which is active (a start/end node or involved in a violated constraint). + */ + void Edge::nodePath(vector<Node*>& nodes, bool allActive = true) { + list<unsigned> ds(dummyNodes.size()); + copy(dummyNodes.begin(),dummyNodes.end(),ds.begin()); + //printf("Edge::nodePath: (%d,%d) dummyNodes:%d\n",startNode,endNode,ds.size()); + path.clear(); + activePath.clear(); + path.push_back(startNode); + activePath.push_back(0); + for(unsigned i=1;i<route->n;i++) { + //printf(" checking segment %d-%d\n",i-1,i); + set<pair<double,unsigned> > pntsOnLineSegment; + for(list<unsigned>::iterator j=ds.begin();j!=ds.end();) { + double px=nodes[*j]->pos[0]; + double py=nodes[*j]->pos[1]; + double ax=route->xs[i-1]; + double ay=route->ys[i-1]; + double bx=route->xs[i]; + double by=route->ys[i]; + double t=0; + list<unsigned>::iterator copyit=j++; + //printf(" px=%f, py=%f, ax=%f, ay=%f, bx=%f, by=%f\n",px,py,ax,ay,bx,by); + if(pointOnLine(px,py,ax,ay,bx,by,t)) { + //printf(" got node %d\n",*copyit); + pntsOnLineSegment.insert(make_pair(t,*copyit)); + ds.erase(copyit); + } + } + for(set<pair<double,unsigned> >::iterator j=pntsOnLineSegment.begin();j!=pntsOnLineSegment.end();j++) { + if(allActive && nodes[j->second]->active) { + activePath.push_back(path.size()); + } + path.push_back(j->second); + } + //printf("\n"); + } + activePath.push_back(path.size()); + path.push_back(endNode); + COLA_ASSERT(ds.empty()); + } + void Edge::createRouteFromPath(std::vector<Node *> const & nodes) { + Route* r=new Route(path.size()); +#ifdef STRAIGHTENER_DEBUG + //printf("Route:"); +#endif + for(unsigned i=0;i<path.size();i++) { + r->xs[i]=nodes[path[i]]->pos[0]; + r->ys[i]=nodes[path[i]]->pos[1]; +#ifdef STRAIGHTENER_DEBUG + //printf("(%f,%f)",r->xs[i],r->ys[i]); +#endif + } +#ifdef STRAIGHTENER_DEBUG + //printf("\n"); +#endif + setRoute(r); + } + + typedef enum {Open, Close} EventType; + struct Event { + EventType type; + Node *v; + Edge *e; + double pos; + Event(EventType t, Node *v, double p) : type(t),v(v),e(nullptr),pos(p) {}; + Event(EventType t, Edge *e, double p) : type(t),v(nullptr),e(e),pos(p) {}; + }; + /* + * the following relation defines a strict weak ordering over events, i.e.: + * irreflexivity: CompareEvents(e,e) == false + * antisymetry: CompareEvents(a,b) => !CompareEvents(b,a) + * transitivity: CompareEvents(a,b) && CompareEvents(b,c) => CompareEvents(a,c) + * transitivity of equivalence: + * !CompareEvents(a,b) && !CompareEvents(b,a) && !CompareEvents(b,c) && !CompareEvents(c,b) + * => !CompareEvents(a,c) && !CompareEvents(c,a) + */ + struct CompareEvents { + bool operator() (Event *const &a, Event *const &b) const { + if(a->pos < b->pos) { + return true; + } else if(a->pos==b->pos) { + // All opens should come before closes when at the same position + if(a->type==Open && b->type==Close) return true; + if(a->type==Close && b->type==Open) return false; + // Edge opens at the same position as node opens, edge comes first + if(a->type==Open && b->type==Open) { + if(a->e && b->v) return true; + if(b->e && a->v) return false; + } + // Edge closes at the same position as node closes, node comes first + if(a->type==Close && b->type==Close) { + if(a->e && b->v) return false; + if(b->e && a->v) return true; + } + } + return false; + } + }; + + /** + * Search along scan line at conjpos for open edges to the left of v + * as far as l, and to the right of v as far as r. + * The result is a list of nodes L (including l,v,r and a bunch of + * new dummy nodes for each edge intersected - excluding edges + * connected to v). + * The new dummy nodes are also added to the end of the canonical + * node list: nodes. + */ + void sortNeighbours(const vpsc::Dim dim, Node * v, Node * l, Node * r, + const double conjpos, vector<Edge*> const & openEdges, + vector<Node *>& L,vector<Node *>& nodes) { + double minpos=-DBL_MAX, maxpos=DBL_MAX; + if(l!=nullptr) { + L.push_back(l); + minpos=l->scanpos; + } + typedef pair<double,Edge*> PosEdgePair; + set<PosEdgePair> sortedEdges; + for(unsigned i=0;i<openEdges.size();i++) { + Edge *e=openEdges[i]; + vector<double> bs; + if(dim==vpsc::HORIZONTAL) { + e->xpos(conjpos,bs); + } else { + e->ypos(conjpos,bs); + } + //std::cerr << "edge(intersections="<<bs.size()<<":("<<e->startNode<<","<<e->endNode<<"))"<<std::endl; + for(vector<double>::iterator it=bs.begin();it!=bs.end();it++) { + sortedEdges.insert(make_pair(*it,e)); + } + } + for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();i++) { + double pos=i->first; + if(pos < minpos) continue; + if(pos > v->scanpos) break; + // if edge is connected (start or end) to v then skip + // need to record start and end positions of edge segment! + Edge* e=i->second; + if(e->startNode==v->id||e->endNode==v->id) continue; + //if(l!=nullptr&&(e->startNode==l->id||e->endNode==l->id)) continue; + //cerr << "edge("<<e->startNode<<","<<e->endNode<<",pts="<<e->pts<<")"<<endl; + // here, we probably want to search for existing dummy + // nodes associated with the same edge within some + // range of (pos,conjpos), rather than creating new ones. + // Would require some sort of quad-tree structure + Node* d=dim==vpsc::HORIZONTAL? + new Node(nodes.size(),pos,conjpos,e): + new Node(nodes.size(),conjpos,pos,e); + L.push_back(d); + nodes.push_back(d); + } + L.push_back(v); + + if(r!=nullptr) { + maxpos=r->scanpos; + } + for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();i++) { + if(i->first < v->scanpos) continue; + if(i->first > maxpos) break; + double pos=i->first; + // if edge is connected (start or end) to v then skip + // need to record start and end positions of edge segment! + Edge* e=i->second; + if(e->startNode==v->id||e->endNode==v->id) continue; + //if(r!=nullptr&&(e->startNode==r->id||e->endNode==r->id)) continue; + //cerr << "edge("<<e->startNode<<","<<e->endNode<<",pts="<<e->pts<<")"<<endl; + Node* d=dim==vpsc::HORIZONTAL? + new Node(nodes.size(),pos,conjpos,e): + new Node(nodes.size(),conjpos,pos,e); + L.push_back(d); + nodes.push_back(d); + } + if(r!=nullptr) { + L.push_back(r); + } + } + static double overlap(vpsc::Dim k, Node const *u, Node const *v) { + if (u->pos[k] <= v->pos[k] && v->getMin(k) < u->getMax(k)) + return u->getMax(k) - v->getMin(k); + if (v->pos[k] <= u->pos[k] && u->getMin(k) < v->getMax(k)) + return v->getMax(k) - u->getMin(k); + return 0; + } + + static cola::SeparationConstraint* createConstraint( + Node* u, Node* v, vpsc::Dim dim) { + double g=u->length[dim]+v->length[dim]; + g/=2; + double sep=v->pos[dim]-u->pos[dim]; + if(sep < g) { + u->active = true; + v->active = true; + } + //cerr << "Constraint: "<< u->id << "+"<<g<<"<="<<v->id<<endl; + return new cola::SeparationConstraint(dim, u->id, v->id, g); + } + + template <typename T> + Event* createEvent( + const vpsc::Dim dim, + const EventType type, + T *v, + double border) { + double pos = (type==Open) ? v->getMin((vpsc::Dim)!dim)-border + : v->getMax((vpsc::Dim)!dim)+border ; + return new Event(type,v,pos); + } + /** + * Generates constraints to prevent node/edge and edge/edge intersections. + * Can be invoked to generate either horizontal or vertical constraints + * depending on dim parameter. + * For horizontal constraints, a vertical scan (from top to bottom) is + * conducted, looking for node/edge boundaries, and then searching along + * the horizontal limit of that boundary for intersections with other + * nodes/edges. + */ + void generateConstraints( + const vpsc::Dim dim, + vector<Node*> & nodes, + vector<Edge*> const & edges, + vector<cola::SeparationConstraint*>& cs, + bool xSkipping = true) { + vector<Event*> events; + double nodeFudge=-0.01, edgeFudge=0; +#ifdef STRAIGHTENER_DEBUG + cout << (dim==vpsc::HORIZONTAL + ?"scanning top to bottom..." + :"scanning left to right...") + << endl; +#endif + for(unsigned i=0;i<nodes.size();i++) { + Node *v=nodes[i]; + if(v->scan) { + v->scanpos=v->pos[dim]; + events.push_back(createEvent(dim,Open,v,nodeFudge)); + events.push_back(createEvent(dim,Close,v,nodeFudge)); + } + } + for(unsigned i=0;i<edges.size();i++) { + Edge *e=edges[i]; + events.push_back(createEvent(dim,Open,e,edgeFudge)); + events.push_back(createEvent(dim,Close,e,edgeFudge)); + } + std::sort(events.begin(),events.end(),CompareEvents()); + + NodeSet openNodes; + vector<Edge*> openEdges; + // scan opening and closing events in order + for(unsigned i=0;i<events.size();i++) { + Event *e=events[i]; + Node *v=e->v; + if(v!=nullptr) { + v->open = true; +#ifdef STRAIGHTENER_DEBUG + printf("NEvent@%f,nid=%d,(%f,%f),w=%f,h=%f,openn=%d,opene=%d\n",e->pos,v->id,v->pos[0],v->pos[1],v->length[0],v->length[1],(int)openNodes.size(),(int)openEdges.size()); +#endif + Node *l=nullptr, *r=nullptr; + if(!openNodes.empty()) { + // it points to the first node to the right of v + NodeSet::iterator it=openNodes.lower_bound(v); + // step left to find the first node to the left of v + while(it--!=openNodes.begin()) { + if(!xSkipping + || dim!=vpsc::HORIZONTAL + || overlap(vpsc::HORIZONTAL,*it,v) <= 0 + || overlap(vpsc::HORIZONTAL,*it,v) <= overlap(vpsc::VERTICAL,*it,v)) { + l=*it; + break; + } +#ifdef STRAIGHTENER_DEBUG + printf("l=%d\n",l->id); +#endif + } + it=openNodes.upper_bound(v); + while(it!=openNodes.end()) { + if(!xSkipping + || dim!=vpsc::HORIZONTAL + || overlap(vpsc::HORIZONTAL,v,*it) <= 0 + || overlap(vpsc::HORIZONTAL,v,*it) <= overlap(vpsc::VERTICAL,v,*it)) { + r=*it; + break; + } + it++; + } + } + vector<Node*> L; + sortNeighbours(dim,v,l,r,e->pos,openEdges,L,nodes); +#ifdef STRAIGHTENER_DEBUG + printf("L=["); + for(unsigned i=0;i<L.size();i++) { + printf("%d ",L[i]->id); + } + printf("]\n"); +#endif + // for each dummy node w in L: + // if w left of v create constraints l<w, w<v + // if w right of v create constraints v<w, w<r + for(vector<Node*>::iterator i=L.begin();i!=L.end();i++) { + Node* w=*i; + if(w->dummy) { + // node is on an edge + Edge *edge=w->edge; + if(w->pos[dim]<v->pos[dim]) { // w left of v + if(l!=nullptr&&!edge->isEnd(l->id)) { + cs.push_back(createConstraint(l,w,dim)); + } + if(!edge->isEnd(v->id)) { + cs.push_back(createConstraint(w,v,dim)); + } + } else { // w right of v + if(!edge->isEnd(v->id)) { + cs.push_back(createConstraint(v,w,dim)); + } + if(r!=nullptr&&!edge->isEnd(r->id)) { + cs.push_back(createConstraint(w,r,dim)); + } + } + } + } + if(e->type==Close) { + if(l!=nullptr) cs.push_back(createConstraint(l,v,dim)); + if(r!=nullptr) cs.push_back(createConstraint(v,r,dim)); + } + } + if(e->type==Open) { + if(v!=nullptr) { + openNodes.insert(v); + } else { +#ifdef STRAIGHTENER_DEBUG + printf("EdgeOpen@%f,eid=%d,(u,v)=(%d,%d)\n", e->pos,e->e->id,e->e->startNode,e->e->endNode); +#endif + e->e->openInd=openEdges.size(); + openEdges.push_back(e->e); + } + } else { + // Close + if(v!=nullptr) { + openNodes.erase(v); + v->open=false; + } else { +#ifdef STRAIGHTENER_DEBUG + printf("EdgeClose@%f,eid=%d,(u,v)=(%d,%d)\n", e->pos,e->e->id,e->e->startNode,e->e->endNode); +#endif + unsigned i=e->e->openInd; + COLA_ASSERT(openEdges.size()>0); + openEdges[i]=openEdges[openEdges.size()-1]; + openEdges[i]->openInd=i; + openEdges.resize(openEdges.size()-1); + } + } + delete e; + } + } + /** + * set up straightener clusters. + * For each cola::cluster c: + * create a straightener::cluster sc + * set each node in c to belong to sc + * set scanpos based on avg pos in scan dir + * create a chain of dummy nodes for cluster boundary + */ + void generateClusterBoundaries( + const vpsc::Dim dim, + vector<straightener::Node*> & nodes, + vector<straightener::Edge*> & edges, + vector<vpsc::Rectangle*> const & rs, + cola::Cluster const & clusterHierarchy, + vector<straightener::Cluster*>& sclusters) { + sclusters.clear(); + for(vector<cola::Cluster*>::const_iterator i + =clusterHierarchy.clusters.begin(); + i!=clusterHierarchy.clusters.end(); i++) { + if(cola::ConvexCluster* c=dynamic_cast<cola::ConvexCluster*>(*i)) { + straightener::Cluster* sc=new straightener::Cluster(c); + // compute scanpos based on average position in scan direction + sc->scanpos=0; + for(set<unsigned>::iterator it= c->nodes.begin(); + it != c->nodes.end(); ++it) { + straightener::Node* u = nodes[*it]; + sc->scanpos+=u->pos[dim]; + u->cluster = sc; + } + sc->scanpos/=c->nodes.size(); + sclusters.push_back(sc); + c->computeBoundary(rs); + // create a chain of dummy nodes for the boundary + Node* first = new Node(nodes.size(),c->hullX[0],c->hullY[0]); + nodes.push_back(first); + Node* u = first; + unsigned i=1; + for(;i<c->hullX.size();i++) { + Node* v = new Node(nodes.size(),c->hullX[i],c->hullY[i]); + nodes.push_back(v); + Edge* e = new Edge(edges.size(),u->id,v->id, + c->hullX[i-1],c->hullY[i-1],c->hullX[i],c->hullY[i]); + edges.push_back(e); + sc->boundary.push_back(e); + u=v; + } + edges.push_back( + new Edge(edges.size(),u->id,first->id, + c->hullX[i-1],c->hullY[i-1],c->hullX[0],c->hullY[0])); + } + } + } + + void Cluster::updateActualBoundary() + { + unsigned n=0; + for(std::vector<Edge*>::const_iterator e=boundary.begin(); + e!=boundary.end();e++) { + n+=(*e)->getRoute()->n; + } + colaCluster->hullX.resize(n); + colaCluster->hullY.resize(n); + unsigned i=0; + for(std::vector<Edge*>::const_iterator e=boundary.begin(); + e!=boundary.end();e++) { + Route const * r=(*e)->getRoute(); + for(unsigned j=0;j<r->n;j++) { + colaCluster->hullX[i]=r->xs[j]; + colaCluster->hullY[i++]=r->ys[j]; + } + } + } + Straightener::Straightener( + const double strength, + const vpsc::Dim dim, + std::vector<vpsc::Rectangle*> const & rs, + cola::FixedList const & fixed, + std::vector<Edge*> const & edges, + vpsc::Variables const & vs, + vpsc::Variables & lvs, + vpsc::Constraints & lcs, + std::valarray<double> &oldCoords, + std::valarray<double> &oldG) + : strength(strength), + dim(dim), + fixed(fixed), + edges(edges), + vs(vs), + lvs(lvs) + { + unsigned n=rs.size(); + for (unsigned i=0;i<n;i++) { + nodes.push_back(new straightener::Node(i,rs[i])); + } + vector<cola::SeparationConstraint*> cs; + straightener::generateConstraints(dim,nodes,edges,cs); + // after generateConstraints we have new dummy nodes at the end of snodes and + // constraints in cs + // need to create variables for dummy nodes in lvs and constraints in lcs + N=nodes.size(); + g.resize(N); + coords.resize(N); + for(unsigned i=0;i<n;i++) { + g[i]=oldG[i]; + coords[i]=oldCoords[i]; + } + for (unsigned i=n;i<N;i++) { + double desiredPos = nodes[i]->pos[dim]; + lvs.push_back(new vpsc::Variable(i,desiredPos,1)); + g[i]=0; + coords[i]=desiredPos; + } + for (vector<cola::SeparationConstraint*>::iterator i=cs.begin();i!=cs.end();i++) { + unsigned lv=(*i)->left(); + unsigned rv=(*i)->right(); + double gap=(*i)->gap; + vpsc::Variable* l = lv<n?vs[lv]:lvs[lv-n]; + vpsc::Variable* r = rv<n?vs[rv]:lvs[rv-n]; + lcs.push_back(new vpsc::Constraint(l,r,gap)); + } + for(unsigned i=0;i<edges.size();i++) { + edges[i]->nodePath(nodes,false); + } + for_each(cs.begin(),cs.end(),cola::delete_object()); + } + Straightener::~Straightener() { + for_each(nodes.begin(),nodes.end(),cola::delete_object()); + } + void Straightener::computeForces(cola::SparseMap &H) { + // hessian matrix: + // diagonal: sum dy2/l^3 + // off-diag: -dy2/l^3 + for(unsigned i=0;i<edges.size();i++) { + //printf("Straightening path:\n"); + //edges[i]->print(); + vector<unsigned>& path=edges[i]->path; + COLA_ASSERT(path.size()>0); + for(unsigned j=1;j<path.size();j++) { + unsigned u=path[j-1], v=path[j]; + double x1=nodes[u]->pos[0], x2=nodes[v]->pos[0], + y1=nodes[u]->pos[1], y2=nodes[v]->pos[1]; + double dx=x1-x2, dy=y1-y2; + double dx2=dx*dx, dy2=dy*dy; + double l=sqrt(dx2+dy2); + if(l<0.0000001) continue; + double f=dim==vpsc::HORIZONTAL?dx:dy; + f*=strength/l; + if(!fixed.check(u)) { g[u]+=f; } + if(!fixed.check(v)) { g[v]-=f; } + double h=dim==vpsc::HORIZONTAL?dy2:dx2; + h*=strength/(l*l*l); + H(u,u)+=h; + H(v,v)+=h; + H(u,v)-=h; + H(v,u)-=h; + } + } + } + double Straightener::computeStress(std::valarray<double> const &coords) { + double stress=0; + for(unsigned i=0;i<edges.size();i++) { + vector<unsigned>& path=edges[i]->path; + COLA_ASSERT(path.size()>0); + for(unsigned j=1;j<path.size();j++) { + unsigned u=path[j-1], v=path[j]; + double x1,x2,y1,y2; + if(dim==vpsc::HORIZONTAL) { + x1=coords[u]; + x2=coords[v]; + y1=nodes[u]->pos[1]; + y2=nodes[v]->pos[1]; + } else { + x1=nodes[u]->pos[0]; + x2=nodes[v]->pos[0]; + y1=coords[u]; + y2=coords[v]; + } + double dx=x1-x2, dy=y1-y2; + double dx2=dx*dx, dy2=dy*dy; + double l=sqrt(dx2+dy2); + stress+=l; + } + } + return strength*stress; + } + double Straightener::computeStress2(std::valarray<double> const &coords) + { + COLA_UNUSED(coords); + + double stress=0; + for(unsigned i=0;i<edges.size();i++) { + double d = edges[i]->idealLength; + double weight=1/(d*d); + //printf("pathLength=%f\n",pathLength(edges[i],nodes)); + double sqrtf=fabs(d-pathLength(edges[i],nodes)); + stress+=weight*sqrtf*sqrtf; + } + return strength*stress; + } + void Straightener::updateNodePositions() { + // real nodes + for (unsigned i=0;i<N;i++) { + Node *n=nodes[i]; + n->pos[dim]=coords[i]; + } + // dummy bend nodes + //printf("got %d dummy nodes\n", (int) lvs.size()); + dummyNodesX.resize(lvs.size()); + dummyNodesY.resize(lvs.size()); + for (unsigned i=0;i<lvs.size();i++) { + COLA_ASSERT(i+vs.size() < nodes.size()); + Node *n=nodes[i+vs.size()]; + dummyNodesX[i]=n->pos[0]; + dummyNodesY[i]=n->pos[1]; + } + } + void Straightener::finalizeRoutes() { + for(unsigned i=0;i<edges.size();i++) { + edges[i]->createRouteFromPath(nodes); + edges[i]->dummyNodes.clear(); + edges[i]->path.clear(); + } + } + void setEdgeLengths(double **D, vector<Edge*> & edges) { + for(unsigned i=0;i<edges.size();i++) { + Edge* e=edges[i]; + e->idealLength=D[e->startNode][e->endNode]; + } + } + double pathLength(Edge const * e, vector<Node*> const & nodes) { + double length=0; + vector<unsigned> const & path=e->path; + for(unsigned i=1;i<path.size();i++) { + Node *u=nodes[path[i-1]], *v=nodes[path[i]]; + double dx=u->pos[0]-v->pos[0]; + double dy=u->pos[1]-v->pos[1]; + length+=sqrt(dx*dx+dy*dy); + } + return length; + } + double computeStressFromRoutes(double strength, vector<Edge*> & edges) { + double stress=0; + for(unsigned i=0;i<edges.size();i++) { + Edge* e=edges[i]; + double d = e->idealLength; + double weight=1/(d*d); + double sqrtf=fabs(d-e->getRoute()->routeLength()); + stress+=weight*sqrtf*sqrtf; + } + return strength*stress; + } +} + diff --git a/src/3rdparty/adaptagrams/libcola/straightener.h b/src/3rdparty/adaptagrams/libcola/straightener.h new file mode 100644 index 0000000..846f4f9 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/straightener.h @@ -0,0 +1,389 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef STRAIGHTENER_H +#define STRAIGHTENER_H + +#include <set> +#include <cfloat> +#include <iostream> +#include <iterator> + +#include "libvpsc/rectangle.h" +#include "libcola/commondefs.h" + +namespace cola { + class Cluster; + class ConvexCluster; + class SeparationConstraint; +} +namespace straightener { + +struct Route { + Route(unsigned n) : n(n), xs(new double[n]), ys(new double[n]) {} + ~Route() { + delete [] xs; + delete [] ys; + } + void print() { + std::cout << "double xs[]={"; + std::copy(xs,xs+n-1,std::ostream_iterator<double>(std::cout,",")); + std::cout << xs[n-1] << "};" << std::endl << "double ys[]={"; + std::copy(ys,ys+n-1,std::ostream_iterator<double>(std::cout,",")); + std::cout << ys[n-1] << "};" << std::endl; + } + void boundingBox(double &xmin,double &ymin,double &xmax,double &ymax) { + xmin=ymin=DBL_MAX; + xmax=ymax=-DBL_MAX; + for(unsigned i=0;i<n;i++) { + xmin=std::min(xmin,xs[i]); + xmax=std::max(xmax,xs[i]); + ymin=std::min(ymin,ys[i]); + ymax=std::max(ymax,ys[i]); + } + } + double routeLength () const { + double length=0; + for(unsigned i=1;i<n;i++) { + double dx=xs[i-1]-xs[i]; + double dy=ys[i-1]-ys[i]; + length+=sqrt(dx*dx+dy*dy); + } + return length; + } + void rerouteAround(vpsc::Rectangle *rect); + unsigned n; + double *xs; + double *ys; +}; +class Node; +struct DebugPoint { + double x,y; +}; +struct DebugLine { + DebugLine(double x0,double y0,double x1,double y1,unsigned colour) + : x0(x0),y0(y0),x1(x1),y1(y1),colour(colour) {} + double x0,y0,x1,y1; + unsigned colour; +}; +class ScanObject { +public: + const unsigned id; + double getMin(vpsc::Dim d) const { + return min[d]; + } + double getMax(vpsc::Dim d) const { + return max[d]; + } + ScanObject(unsigned id) : id(id) {} +protected: + double min[2], max[2]; +}; +class Edge : public ScanObject { +public: + unsigned openInd; // position in openEdges + unsigned startNode, endNode; + double idealLength; + std::vector<unsigned> dummyNodes; + std::vector<unsigned> path; + std::vector<unsigned> activePath; + std::vector<DebugPoint> debugPoints; + std::vector<DebugLine> debugLines; + void print() { + printf("Edge[%d]=(%d,%d)\n",id,startNode,endNode); + route->print(); + } + // if the edge route intersects with any of the rectangles in rects then reroute + // those parts of the route around the rectangle boundaries + void rerouteAround(std::vector<vpsc::Rectangle*> const &rects) { + unsigned rid=0; + for(std::vector<vpsc::Rectangle*>::const_iterator r=rects.begin();r!=rects.end();r++,rid++) { + if(rid!=startNode && rid!=endNode) { + route->rerouteAround(*r); + } + } + updateBoundingBox(); + } + // Edge with a non-trivial route + Edge(unsigned id, unsigned start, unsigned end, Route* route) + : ScanObject(id), startNode(start), endNode(end), route(route) + { + updateBoundingBox(); + } + // Edge with a trivial route + Edge(unsigned id, unsigned start, unsigned end, + double x1, double y1, double x2, double y2) + : ScanObject(id), startNode(start), endNode(end) { + route = new Route(2); + route->xs[0]=x1; route->ys[0]=y1; + route->xs[1]=x2; route->ys[1]=y2; + updateBoundingBox(); + } + ~Edge() { + delete route; + } + bool isEnd(unsigned n) const { + if(startNode==n||endNode==n) return true; + return false; + } + void nodePath(std::vector<Node*>& nodes, bool allActive); + void createRouteFromPath(std::vector<Node *> const & nodes); + void xpos(double y, std::vector<double>& xs) const { + // search line segments for intersection points with y pos + for(unsigned i=1;i<route->n;i++) { + double ax=route->xs[i-1], bx=route->xs[i], ay=route->ys[i-1], by=route->ys[i]; + double r=(y-ay)/(by-ay); + // as long as y is between ay and by then r>0 + if(r>=0&&r<=1) { + xs.push_back(ax+(bx-ax)*r); + } + } + } + void ypos(double x, std::vector<double>& ys) const { + // search line segments for intersection points with x pos + for(unsigned i=1;i<route->n;i++) { + double ax=route->xs[i-1], bx=route->xs[i], ay=route->ys[i-1], by=route->ys[i]; + double r=(x-ax)/(bx-ax); + // as long as y is between ax and bx then r>0 + if(r>0&&r<=1) { + ys.push_back(ay+(by-ay)*r); + } + } + } + Route const * getRoute() const { + return route; + } + void setRoute(Route * r) { + delete route; + route=r; + updateBoundingBox(); + } +private: + void updateBoundingBox() { + route->boundingBox(min[0],min[1],max[0],max[1]); + } + Route* route; +}; +class Straightener { +public: + Straightener( + const double strength, + const vpsc::Dim dim, + std::vector<vpsc::Rectangle*> const & rs, + cola::FixedList const & fixed, + std::vector<Edge*> const & edges, + vpsc::Variables const & vs, + vpsc::Variables & lvs, + vpsc::Constraints & lcs, + std::valarray<double> & oldCoords, + std::valarray<double> & oldG); + ~Straightener(); + void updateNodePositions(); + void finalizeRoutes(); + void computeForces(cola::SparseMap &H); + void computeForces2(cola::SparseMap &H); + double computeStress(std::valarray<double> const &coords); + double computeStress2(std::valarray<double> const &coords); + std::valarray<double> dummyNodesX; + std::valarray<double> dummyNodesY; + std::valarray<double> g; + std::valarray<double> coords; + unsigned N; +private: + double strength; + const vpsc::Dim dim; + cola::FixedList const & fixed; + std::vector<Edge*> const & edges; + vpsc::Variables const & vs; + vpsc::Variables & lvs; + std::vector<Node*> nodes; + double len(const unsigned u, const unsigned v, + double& dx, double& dy, + double& dx2, double& dy2); + double gRule1(const unsigned a, const unsigned b); + double gRule2(const unsigned a, const unsigned b, const unsigned c); + double hRuleD1(const unsigned u, const unsigned v, const double sqrtf); + double hRuleD2(const unsigned u, const unsigned v, const unsigned w, const double sqrtf); + double hRule2(const unsigned u, const unsigned v, const unsigned w, const double sqrtf); + double hRule3(const unsigned u, const unsigned v, const unsigned w, const double sqrtf); + double hRule4(const unsigned a, const unsigned b, const unsigned c, const unsigned d); + double hRule56(const unsigned u, const unsigned v, + const unsigned a, const unsigned b, const unsigned c); + double hRule7(const unsigned a, const unsigned b, + const unsigned c, const unsigned d, const double sqrtf); + double hRule8(const unsigned u, const unsigned v, const unsigned w, + const unsigned a, const unsigned b, const unsigned c); +}; +class Cluster { +public: + cola::ConvexCluster* colaCluster; + Cluster(cola::ConvexCluster* c) : colaCluster(c) {} + double scanpos; + std::vector<Edge*> boundary; + void updateActualBoundary(); +}; +class Node : public ScanObject { +public: + Cluster* cluster; + // Nodes may optionally belong to a cluster. + // Neg cluster_id means no cluster - i.e. top-level membership. + double pos[2]; + double scanpos; + double length[2]; + Edge* edge; + bool dummy; // nodes on edge paths (but not ends) are dummy + bool scan; // triggers scan events + bool active; // node is active if it is not dummy or is dummy and involved in + // a violated constraint + bool open; // a node is opened (if scan is true) when the scanline first reaches + // its boundary and closed when the scanline leaves it. + Node(unsigned id, vpsc::Rectangle const * r) : + ScanObject(id),cluster(nullptr), + edge(nullptr),dummy(false),scan(true),active(true),open(false) { + for(unsigned i=0;i<2;i++) { + pos[i]=r->getCentreD(i); + min[i]=r->getMinD(i); + max[i]=r->getMaxD(i); + length[i]=r->length(i); + } + } + Node(unsigned id, const double x, const double y) : + ScanObject(id),cluster(nullptr), + edge(nullptr),dummy(false),scan(false),active(true),open(false) { + pos[vpsc::HORIZONTAL]=x; + pos[vpsc::VERTICAL]=y; + for(unsigned i=0;i<2;i++) { + length[i]=4; + min[i]=pos[i]-length[i]/2.0; + max[i]=pos[i]+length[i]/2.0; + } + } + double euclidean_distance(Node const * v) const { + double dx=pos[0]-v->pos[0]; + double dy=pos[1]-v->pos[1]; + return sqrt(dx*dx+dy*dy); + } + +private: + friend void sortNeighbours(const vpsc::Dim dim, Node * v, Node * l, Node * r, + const double conjpos, std::vector<Edge*> const & openEdges, + std::vector<Node *>& L, std::vector<Node *>& nodes); + Node(const unsigned id, const double x, const double y, Edge* e) : + ScanObject(id),cluster(nullptr), + edge(e),dummy(true),scan(false),active(false) { + pos[vpsc::HORIZONTAL]=x; + pos[vpsc::VERTICAL]=y; + for(unsigned i=0;i<2;i++) { + length[i]=4; + min[i]=pos[i]-length[i]/2.0; + max[i]=pos[i]+length[i]/2.0; + } + e->dummyNodes.push_back(id); + } +}; +struct CmpNodePos { + bool operator() (const Node* u, const Node* v) const { + double upos = u->scanpos; + double vpos = v->scanpos; + bool tiebreaker = u < v; + if (u->cluster != v->cluster) { + if(u->cluster!=nullptr) { + upos = u->cluster->scanpos; + } + if(v->cluster!=nullptr) { + vpos = v->cluster->scanpos; + } + tiebreaker = u->cluster < v->cluster; + } + if (upos < vpos) { + return true; + } + if (vpos < upos) { + return false; + } + return tiebreaker; + } +}; +typedef std::set<Node*,CmpNodePos> NodeSet; +// defines references to three variables for which the goal function +// will be altered to prefer points u-b-v are in a linear arrangement +// such that b is placed at u+t(v-u). +struct LinearConstraint { + LinearConstraint( + Node const & u, + Node const & v, + Node const & b, + double w) + : u(u.id),v(v.id),b(b.id),w(w) + { + // from cosine rule: ub.uv/|uv|=|ub|cos(theta) + double uvx = v.pos[0] - u.pos[0], + uvy = v.pos[1] - u.pos[1], + ubx = b.pos[0] - u.pos[0], + uby = b.pos[1] - u.pos[1], + duv2 = uvx * uvx + uvy * uvy; + if(duv2 < 0.0001) { + t=0; + } else { + t = (uvx * ubx + uvy * uby)/duv2; + } + duu=(1-t)*(1-t); + duv=t*(1-t); + dub=t-1; + dvv=t*t; + dvb=-t; + dbb=1; + //printf("New LC: t=%f\n",t); + } + unsigned u; + unsigned v; + unsigned b; + double w; // weight + double t; + // 2nd partial derivatives of the goal function + // (X[b] - (1-t) X[u] - t X[v])^2 + double duu; + double duv; + double dub; + double dvv; + double dvb; + double dbb; +}; +void setEdgeLengths(double **D, std::vector<Edge*> & edges); +double pathLength(Edge const * e, std::vector<Node*> const & nodes); +double computeStressFromRoutes(double strength, std::vector<Edge*> & edges); +typedef std::vector<LinearConstraint*> LinearConstraints; +void generateConstraints( + const vpsc::Dim dim, + std::vector<Node*> & nodes, + std::vector<Edge*> const & edges, + std::vector<cola::SeparationConstraint*>& cs, + bool xSkipping); +void nodePath(Edge& e, std::vector<Node*>& nodes, std::vector<unsigned>& path); +void generateClusterBoundaries( + const vpsc::Dim dim, + std::vector<Node*> & nodes, + std::vector<Edge*> & edges, + std::vector<vpsc::Rectangle*> const & rs, + cola::Cluster const & clusterHierarchy, + std::vector<straightener::Cluster*>& sclusters); + +} // namespace straightener +#endif diff --git a/src/3rdparty/adaptagrams/libcola/tests/FixedRelativeConstraint01.cpp b/src/3rdparty/adaptagrams/libcola/tests/FixedRelativeConstraint01.cpp new file mode 100755 index 0000000..378219e --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/FixedRelativeConstraint01.cpp @@ -0,0 +1,51 @@ +#include <vector> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + double defaultEdgeLength=40; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + std::vector<unsigned> fixedShapes; + + double textW = 100; + double textH = 10; + double circleW = 5; + double circleH = 5; + + rect = new vpsc::Rectangle(303-circleW, 303+circleW, 300-circleH, 300+circleH); + rs.push_back(rect); + fixedShapes.push_back(rs.size() - 1); + + rect = new vpsc::Rectangle(310-circleW, 310+circleW, 302-circleH, 302+circleH); + rs.push_back(rect); + fixedShapes.push_back(rs.size() - 1); + + rect = new vpsc::Rectangle(313-circleW, 313+circleW, 297-circleH, 297+circleH); + rs.push_back(rect); + fixedShapes.push_back(rs.size() - 1); + + rect = new vpsc::Rectangle(300-textW, 300+textW, 300-textH, 300+textH); + rs.push_back(rect); + + rect = new vpsc::Rectangle(310-textW, 310+textW, 305-textH, 305+textH); + rs.push_back(rect); + + rect = new vpsc::Rectangle(317-textW, 317+textW, 295-textH, 295+textH); + rs.push_back(rect); + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength); + alg.setAvoidNodeOverlaps(true); + + ccs.push_back(new FixedRelativeConstraint(rs, fixedShapes, true)); + alg.setConstraints(ccs); + + alg.makeFeasible(); + + // Can be used to output a "libcola-debug.svg" file: + //alg.outputInstanceToSVG(); + alg.freeAssociatedObjects(); + + return 0; +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/Makefile.am b/src/3rdparty/adaptagrams/libcola/tests/Makefile.am new file mode 100644 index 0000000..a73ff82 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/Makefile.am @@ -0,0 +1,68 @@ +AM_CPPFLAGS = -I$(top_srcdir) $(CAIROMM_CFLAGS) + +LDADD = \ + $(top_builddir)/libvpsc/libvpsc.la \ + $(top_builddir)/libtopology/libtopology.la \ + $(top_builddir)/libcola/libcola.la \ + $(top_builddir)/libavoid/libavoid.la \ + $(CAIROMM_LIBS) + +check_PROGRAMS = random_graph page_bounds constrained unsatisfiable invalid makefeasible rectclustershapecontainment FixedRelativeConstraint01 StillOverlap01 StillOverlap02 shortest_paths rectangularClusters01 overlappingClusters01 overlappingClusters02 overlappingClusters04 initialOverlap +#check_PROGRAMS = unconstrained constrained containment shortest_paths connected_components large_graph convex_hull scale_free trees random_graph large_graph topology boundary planar #resize +#check_PROGRAMS = topology boundary planar resize resizealignment + +# problem_SOURCES = problem.cpp + +initialOverlap_SOURCES = initialOverlap.cpp + +overlappingClusters01_SOURCES = overlappingClusters01.cpp +overlappingClusters02_SOURCES = overlappingClusters02.cpp +overlappingClusters04_SOURCES = overlappingClusters04.cpp + +rectangularClusters01_SOURCES = rectangularClusters01.cpp + +StillOverlap01_SOURCES = StillOverlap01.cpp +StillOverlap02_SOURCES = StillOverlap02.cpp + +FixedRelativeConstraint01_SOURCES = FixedRelativeConstraint01.cpp + +rectclustershapecontainment_SOURCES = rectclustershapecontainment.cpp + +random_graph_SOURCES = random_graph.cpp + +page_bounds_SOURCES = page_bounds.cpp + +constrained_SOURCES = constrained.cpp + +unsatisfiable_SOURCES = unsatisfiable.cpp + +invalid_SOURCES = invalid.cpp + +makefeasible_LDADD = $(LDADD) $(top_srcdir)/libavoid/libavoid.la +makefeasible_SOURCES = makefeasible02.cpp + +shortest_paths_SOURCES = shortest_paths.cpp +#unconstrained_SOURCES = unconstrained.cpp +#containment_SOURCES = containment.cpp +#topology_SOURCES = topology.cpp +#boundary_SOURCES = boundary.cpp +#resize_SOURCES = resize.cpp +#resizealignment_SOURCES = resizealignment.cpp +#planar_SOURCES = planar.cpp +#connected_components_SOURCES = connected_components.cpp +# test Requires boost +#sparse_matrix_SOURCES = sparse_matrix.cpp +#convex_hull_SOURCES = convex_hull.cpp +#convex_hull_LDADD = $(LDADD) -lcairo -lcairomm-1.0 +#aarontest_SOURCES = aarontest.cpp +#aarontest_LDADD = $(top_srcdir)/libcola/libcola.la $(top_builddir)/libvpsc/libvpsc.la -lcairo -lcairomm-1.0 +#qo1_SOURCES = qo1.c +#qo1_LDADD = -L$(mosek_home)/bin -lmosek -lguide -limf +#small_graph_SOURCES = small_graph.cpp +#large_graph_SOURCES = large_graph.cpp +#gml_graph_LDADD = $(common_LDADD) /usr/lib/libboost_regex.so +#gml_graph_SOURCES = gml_graph.cpp +#scale_free_SOURCES = scale_free.cpp +#trees_SOURCES = trees.cpp + +TESTS = $(check_PROGRAMS) diff --git a/src/3rdparty/adaptagrams/libcola/tests/StillOverlap01.cpp b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap01.cpp new file mode 100755 index 0000000..1b87767 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap01.cpp @@ -0,0 +1,221 @@ +#include <vector> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + double defaultEdgeLength=40; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + rect = new vpsc::Rectangle(210, 240, 83.5, 113.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(210, 240, 125.5, 155.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(377, 407, 43.5, 73.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(251, 281, 43.5, 73.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(110, 140, 43.5, 73.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(29, 79, 55.5, 105.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(427, 477, 32.5, 82.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(300, 350, 32.5, 82.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(171, 221, 32.5, 82.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(33, 83, 115.5, 165.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 572, 115.5, 165.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(519, 569, 35.5, 85.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(192, 258, 123.5, 173.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(192, 258, 65.5, 115.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(359, 425, -16.5, 33.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(233, 299, -16.5, 33.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(154, 220, 33.5, 83.5); + rs.push_back(rect); + + AlignmentConstraint *alignment140600592030544 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592030544->addShape(1, 0); + alignment140600592030544->addShape(0, 0); + ccs.push_back(alignment140600592030544); + + AlignmentConstraint *alignment140600592030848 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592030848->addShape(2, 0); + ccs.push_back(alignment140600592030848); + + AlignmentConstraint *alignment140600592031040 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592031040->addShape(3, 0); + ccs.push_back(alignment140600592031040); + + AlignmentConstraint *alignment140600592031168 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592031168->addShape(4, 0); + ccs.push_back(alignment140600592031168); + + AlignmentConstraint *alignment140600592031296 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592031296->addShape(5, 0); + ccs.push_back(alignment140600592031296); + + AlignmentConstraint *alignment140600592031456 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592031456->addShape(6, 0); + ccs.push_back(alignment140600592031456); + + AlignmentConstraint *alignment140600592031616 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592031616->addShape(7, 0); + ccs.push_back(alignment140600592031616); + + AlignmentConstraint *alignment140600592031776 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592031776->addShape(8, 0); + ccs.push_back(alignment140600592031776); + + AlignmentConstraint *alignment140600592031936 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592031936->addShape(9, 0); + ccs.push_back(alignment140600592031936); + + AlignmentConstraint *alignment140600592032240 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592032240->addShape(10, 0); + ccs.push_back(alignment140600592032240); + + AlignmentConstraint *alignment140600592032400 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592032400->addShape(11, 0); + ccs.push_back(alignment140600592032400); + + SeparationConstraint *separation140600592044112 = new SeparationConstraint(vpsc::XDIM, alignment140600592031296, alignment140600592031936, 4, false); + ccs.push_back(separation140600592044112); + + SeparationConstraint *separation140600592045280 = new SeparationConstraint(vpsc::XDIM, alignment140600592031936, alignment140600592031168, 67, false); + ccs.push_back(separation140600592045280); + + SeparationConstraint *separation140600592045376 = new SeparationConstraint(vpsc::XDIM, alignment140600592031168, alignment140600592031776, 71, false); + ccs.push_back(separation140600592045376); + + SeparationConstraint *separation140600592045520 = new SeparationConstraint(vpsc::XDIM, alignment140600592031776, alignment140600592030544, 29, false); + ccs.push_back(separation140600592045520); + + SeparationConstraint *separation140600592045696 = new SeparationConstraint(vpsc::XDIM, alignment140600592030544, alignment140600592031040, 41, false); + ccs.push_back(separation140600592045696); + + SeparationConstraint *separation140600592045872 = new SeparationConstraint(vpsc::XDIM, alignment140600592031040, alignment140600592031616, 59, false); + ccs.push_back(separation140600592045872); + + SeparationConstraint *separation140600592043472 = new SeparationConstraint(vpsc::XDIM, alignment140600592031616, alignment140600592030848, 67, false); + ccs.push_back(separation140600592043472); + + SeparationConstraint *separation140600592043648 = new SeparationConstraint(vpsc::XDIM, alignment140600592030848, alignment140600592031456, 60, false); + ccs.push_back(separation140600592043648); + + SeparationConstraint *separation140600592043824 = new SeparationConstraint(vpsc::XDIM, alignment140600592031456, alignment140600592032400, 92, false); + ccs.push_back(separation140600592043824); + + SeparationConstraint *separation140600592046048 = new SeparationConstraint(vpsc::XDIM, alignment140600592032400, alignment140600592032240, 3, false); + ccs.push_back(separation140600592046048); + + AlignmentConstraint *alignment140600592044208 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140600592044208->addShape(0, 0); + ccs.push_back(alignment140600592044208); + + AlignmentConstraint *alignment140600592044368 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140600592044368->addShape(5, 0); + ccs.push_back(alignment140600592044368); + + AlignmentConstraint *alignment140600592044528 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140600592044528->addShape(1, 0); + alignment140600592044528->addShape(9, 0); + alignment140600592044528->addShape(10, 0); + ccs.push_back(alignment140600592044528); + + AlignmentConstraint *alignment140600592044752 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140600592044752->addShape(6, 0); + alignment140600592044752->addShape(4, 0); + alignment140600592044752->addShape(7, 0); + alignment140600592044752->addShape(8, 0); + alignment140600592044752->addShape(3, 0); + alignment140600592044752->addShape(11, 0); + alignment140600592044752->addShape(2, 0); + ccs.push_back(alignment140600592044752); + + SeparationConstraint *separation140600592045088 = new SeparationConstraint(vpsc::YDIM, alignment140600592044752, alignment140600592044368, 22.1429, false); + ccs.push_back(separation140600592045088); + + SeparationConstraint *separation140600590330720 = new SeparationConstraint(vpsc::YDIM, alignment140600592044368, alignment140600592044208, 18, false); + ccs.push_back(separation140600590330720); + + SeparationConstraint *separation140600590330896 = new SeparationConstraint(vpsc::YDIM, alignment140600592044208, alignment140600592044528, 42, false); + ccs.push_back(separation140600590330896); + + AlignmentConstraint *alignment140600590331072 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600590331072->addShape(0, 0); + alignment140600590331072->addShape(12, 0); + ccs.push_back(alignment140600590331072); + + SeparationConstraint *separation140600590331376 = new SeparationConstraint(vpsc::YDIM, 0, 12, 50, true); + ccs.push_back(separation140600590331376); + + AlignmentConstraint *alignment140600590331520 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600590331520->addShape(1, 0); + alignment140600590331520->addShape(13, 0); + ccs.push_back(alignment140600590331520); + + SeparationConstraint *separation140600590331744 = new SeparationConstraint(vpsc::YDIM, 1, 13, -50, true); + ccs.push_back(separation140600590331744); + + AlignmentConstraint *alignment140600590331888 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600590331888->addShape(2, 0); + alignment140600590331888->addShape(14, 0); + ccs.push_back(alignment140600590331888); + + SeparationConstraint *separation140600590332112 = new SeparationConstraint(vpsc::YDIM, 2, 14, -50, true); + ccs.push_back(separation140600590332112); + + AlignmentConstraint *alignment140600592043200 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140600592043200->addShape(3, 0); + alignment140600592043200->addShape(15, 0); + ccs.push_back(alignment140600592043200); + + SeparationConstraint *separation140600590332784 = new SeparationConstraint(vpsc::YDIM, 3, 15, -50, true); + ccs.push_back(separation140600590332784); + + AlignmentConstraint *alignment140600590332880 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140600590332880->addShape(4, 0); + alignment140600590332880->addShape(16, 0); + ccs.push_back(alignment140600590332880); + + SeparationConstraint *separation140600590333104 = new SeparationConstraint(vpsc::XDIM, 4, 16, 62, true); + ccs.push_back(separation140600590333104); + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength); + alg.setAvoidNodeOverlaps(true); + RootCluster *cluster140600590333360 = new RootCluster(); + alg.setClusterHierarchy(cluster140600590333360); + alg.setConstraints(ccs); + alg.makeFeasible(); + alg.run(); + alg.outputInstanceToSVG("test-StillOverlap01"); + alg.freeAssociatedObjects(); + return 0; +}; + diff --git a/src/3rdparty/adaptagrams/libcola/tests/StillOverlap02.cpp b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap02.cpp new file mode 100755 index 0000000..c45eef6 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap02.cpp @@ -0,0 +1,1863 @@ +#include <vector> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + double defaultEdgeLength=40; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + rect = new vpsc::Rectangle(80.8448, 110.845, -23.9565, 6.04346); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-121.155, 128.845, -212.957, -142.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(209.095, 239.095, -389.957, -359.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(209.095, 239.095, -240.957, -210.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(274.428, 304.428, -130.957, -100.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(140.845, 170.845, -78.9565, -48.9565); + rs.push_back(rect); + + rect = new vpsc::Rectangle(80.8448, 110.845, -55.9565, -25.9565); + rs.push_back(rect); + + rect = new vpsc::Rectangle(501.428, 531.428, -232.623, -202.623); + rs.push_back(rect); + + rect = new vpsc::Rectangle(501.428, 531.428, -140.623, -110.623); + rs.push_back(rect); + + rect = new vpsc::Rectangle(485.428, 515.428, -33.3565, -3.35654); + rs.push_back(rect); + + rect = new vpsc::Rectangle(737.928, 767.928, -133.957, -103.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(140.845, 170.845, 314.043, 344.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375.428, 405.428, 191.443, 221.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(443.428, 473.428, 202.243, 232.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(558.428, 588.428, 136.777, 166.777); + rs.push_back(rect); + + rect = new vpsc::Rectangle(634.214, 664.214, 136.777, 166.777); + rs.push_back(rect); + + rect = new vpsc::Rectangle(764.214, 794.214, 136.777, 166.777); + rs.push_back(rect); + + rect = new vpsc::Rectangle(819.095, 849.095, 156.443, 186.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(853.595, 883.595, 76.0435, 106.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(711.928, 741.928, 202.243, 232.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(542.428, 572.428, 280.443, 310.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(296.428, 326.428, 440.943, 470.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(202.428, 232.428, 693.943, 723.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(407.428, 473.428, 685.943, 735.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375.428, 405.428, 693.943, 723.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(542.428, 572.428, 632.443, 662.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(517.428, 547.428, 444.443, 474.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(566.928, 596.928, 444.443, 474.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(879.345, 909.345, 280.443, 310.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(879.345, 909.345, 478.443, 508.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(836.095, 866.095, 332.443, 362.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(797.928, 827.928, 436.443, 466.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(55.8448, 85.8448, 507.443, 537.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375.428, 405.428, 1026.76, 1056.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375.428, 405.428, 1074.76, 1104.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-102.489, -72.4885, 1051.76, 1081.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(797.928, 827.928, 802.515, 832.515); + rs.push_back(rect); + + rect = new vpsc::Rectangle(839.928, 1079.93, 198.443, 268.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(768, 1008, 844.515, 914.515); + rs.push_back(rect); + + rect = new vpsc::Rectangle(626.928, 656.928, 972.765, 1002.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(426.956, 456.956, 972.765, 1002.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(224.428, 254.428, 972.765, 1002.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375.428, 405.428, 870.765, 900.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(255.428, 285.428, 870.765, 900.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(744.928, 774.928, 332.443, 362.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(30, 354, -347.957, -302.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-183.905, 137.095, 68.0435, 252.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375.428, 405.428, 530.443, 560.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375.428, 405.428, 332.443, 362.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(1.84481, 31.8448, 870.765, 900.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(127.095, 157.095, 870.765, 900.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(991.345, 1021.34, 478.443, 508.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(991.345, 1021.34, 600.443, 630.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(38.8448, 68.8448, 693.943, 723.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-58.1552, -28.1552, 768.765, 798.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(130.845, 180.845, -399.957, -349.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(130.845, 180.845, -250.957, -200.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-112.489, -62.4885, -43.3565, 6.64346); + rs.push_back(rect); + + rect = new vpsc::Rectangle(289.428, 339.428, 192.243, 242.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(532.428, 582.428, 192.243, 242.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(567.428, 617.428, -150.623, -100.623); + rs.push_back(rect); + + rect = new vpsc::Rectangle(843.595, 893.595, -150.623, -100.623); + rs.push_back(rect); + + rect = new vpsc::Rectangle(616.928, 666.928, -43.3565, 6.64346); + rs.push_back(rect); + + rect = new vpsc::Rectangle(787.928, 837.928, -43.3565, 6.64346); + rs.push_back(rect); + + rect = new vpsc::Rectangle(869.345, 919.345, 520.443, 570.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(289.428, 339.428, 322.443, 372.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(130.845, 180.845, 430.943, 480.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(869.345, 919.345, 374.443, 424.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(286.428, 336.428, 683.943, 733.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(130.845, 180.845, 520.443, 570.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(130.845, 180.845, 1116.76, 1166.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(676.928, 726.928, 962.765, 1012.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(520.428, 570.428, 962.765, 1012.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(336.428, 386.428, 962.765, 1012.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(676.928, 726.928, 860.765, 910.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(130.845, 180.845, 1064.76, 1114.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(425.428, 475.428, 860.765, 910.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(305.428, 355.428, 860.765, 910.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(787.928, 837.928, 1064.76, 1114.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(532.428, 582.428, 520.443, 570.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(787.928, 837.928, 192.243, 242.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(295.428, 345.428, 520.443, 570.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(475.428, 525.428, 683.943, 733.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(113.095, 163.095, 683.943, 733.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-19.1552, 30.8448, 520.443, 570.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(295.428, 345.428, 572.443, 622.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(295.428, 345.428, 631.943, 681.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(289.428, 339.428, -43.3565, 6.64346); + rs.push_back(rect); + + rect = new vpsc::Rectangle(177.428, 227.428, 860.765, 910.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(289.428, 339.428, -250.957, -200.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(532.428, 582.428, 322.443, 372.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(787.928, 837.928, 622.443, 672.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(556.928, 606.928, 860.765, 910.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(139.095, 189.095, 66.0435, 116.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-68.1552, -18.1552, 683.943, 733.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(425.428, 475.428, 758.765, 808.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(177.428, 227.428, 758.765, 808.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(51.8448, 101.845, 860.765, 910.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-68.1552, -18.1552, 860.765, 910.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(305.428, 355.428, 758.765, 808.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(616.928, 666.928, 218.443, 268.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(981.345, 1031.34, 520.443, 570.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(981.345, 1031.34, 656.943, 706.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(592.428, 839.428, 486.443, 556.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(626.928, 656.928, 596.443, 626.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(616.928, 666.928, 656.943, 706.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(616.928, 666.928, 750.515, 800.515); + rs.push_back(rect); + + rect = new vpsc::Rectangle(626.928, 656.928, 717.515, 747.515); + rs.push_back(rect); + + rect = new vpsc::Rectangle(209.095, 239.095, 76.0435, 106.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(62.8448, 128.845, 16.0435, 66.0435); + rs.push_back(rect); + + rect = new vpsc::Rectangle(191.095, 257.095, -449.957, -399.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(191.095, 257.095, -300.957, -250.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(194.428, 260.428, -140.957, -90.9565); + rs.push_back(rect); + + rect = new vpsc::Rectangle(184.845, 250.845, -88.9565, -38.9565); + rs.push_back(rect); + + rect = new vpsc::Rectangle(62.8448, 128.845, -115.957, -65.9565); + rs.push_back(rect); + + rect = new vpsc::Rectangle(483.428, 549.428, -292.623, -242.623); + rs.push_back(rect); + + rect = new vpsc::Rectangle(483.428, 549.428, -200.623, -150.623); + rs.push_back(rect); + + rect = new vpsc::Rectangle(467.428, 533.428, -93.3565, -43.3565); + rs.push_back(rect); + + rect = new vpsc::Rectangle(719.928, 785.928, -93.9565, -43.9565); + rs.push_back(rect); + + rect = new vpsc::Rectangle(122.845, 188.845, 254.043, 304.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(357.428, 423.428, 131.443, 181.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(425.428, 491.428, 142.243, 192.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(540.428, 606.428, 76.7768, 126.777); + rs.push_back(rect); + + rect = new vpsc::Rectangle(616.214, 682.214, 76.7768, 126.777); + rs.push_back(rect); + + rect = new vpsc::Rectangle(684.214, 750.214, 126.777, 176.777); + rs.push_back(rect); + + rect = new vpsc::Rectangle(863.095, 929.095, 146.443, 196.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(897.595, 963.595, 66.0435, 116.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(693.928, 759.928, 242.243, 292.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(586.428, 652.428, 270.443, 320.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(278.428, 344.428, 380.943, 430.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(184.428, 250.428, 633.943, 683.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(357.428, 423.428, 633.943, 683.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(524.428, 590.428, 572.443, 622.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(437.428, 503.428, 434.443, 484.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(610.928, 676.928, 434.443, 484.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(923.345, 989.345, 270.443, 320.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(923.345, 989.345, 468.443, 518.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(880.095, 946.095, 322.443, 372.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(841.928, 907.928, 426.443, 476.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(37.8448, 103.845, 447.443, 497.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(357.428, 423.428, 1066.76, 1116.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(357.428, 423.428, 1014.76, 1064.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-58.4885, 7.51148, 1041.76, 1091.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(841.928, 907.928, 792.515, 842.515); + rs.push_back(rect); + + rect = new vpsc::Rectangle(608.928, 674.928, 912.765, 962.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(408.956, 474.956, 912.765, 962.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(268.428, 334.428, 962.765, 1012.76); + rs.push_back(rect); + + rect = new vpsc::Rectangle(357.428, 423.428, 810.765, 860.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(237.428, 303.428, 810.765, 860.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(664.928, 730.928, 322.443, 372.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(357.428, 423.428, 470.443, 520.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(357.428, 423.428, 272.443, 322.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-16.1552, 49.8448, 810.765, 860.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(109.095, 175.095, 810.765, 860.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(1035.34, 1101.34, 468.443, 518.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(1035.34, 1101.34, 590.443, 640.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(20.8448, 86.8448, 633.943, 683.943); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-14.1552, 51.8448, 758.765, 808.765); + rs.push_back(rect); + + rect = new vpsc::Rectangle(670.928, 736.928, 586.443, 636.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(670.928, 736.928, 707.515, 757.515); + rs.push_back(rect); + + rect = new vpsc::Rectangle(191.095, 257.095, 16.0435, 66.0435); + rs.push_back(rect); + + rect = new vpsc::Rectangle(58.8448, 128.845, -192.957, -142.957); + rs.push_back(rect); + + rect = new vpsc::Rectangle(839.928, 909.928, 218.443, 268.443); + rs.push_back(rect); + + rect = new vpsc::Rectangle(768.5, 838.5, 844.515, 894.515); + rs.push_back(rect); + + rect = new vpsc::Rectangle(67.0948, 137.095, 150.043, 200.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(67.0948, 137.095, 202.043, 252.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-36.9052, 13.0948, 182.043, 252.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(15.0948, 65.0948, 182.043, 252.043); + rs.push_back(rect); + + rect = new vpsc::Rectangle(592.428, 662.428, 486.443, 536.443); + rs.push_back(rect); + + AlignmentConstraint *alignment1114387328 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114387328->addShape(4, 0); + ccs.push_back(alignment1114387328); + + AlignmentConstraint *alignment1103856272 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103856272->addShape(0, 0); + alignment1103856272->addShape(6, 0); + ccs.push_back(alignment1103856272); + + AlignmentConstraint *alignment1102536224 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1102536224->addShape(7, 0); + alignment1102536224->addShape(8, 0); + ccs.push_back(alignment1102536224); + + AlignmentConstraint *alignment1113412976 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1113412976->addShape(10, 0); + ccs.push_back(alignment1113412976); + + AlignmentConstraint *alignment1103859296 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103859296->addShape(13, 0); + ccs.push_back(alignment1103859296); + + AlignmentConstraint *alignment1108560576 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1108560576->addShape(14, 0); + ccs.push_back(alignment1108560576); + + AlignmentConstraint *alignment1102536400 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1102536400->addShape(15, 0); + ccs.push_back(alignment1102536400); + + AlignmentConstraint *alignment1102857472 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1102857472->addShape(16, 0); + ccs.push_back(alignment1102857472); + + AlignmentConstraint *alignment1103856000 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103856000->addShape(17, 0); + ccs.push_back(alignment1103856000); + + AlignmentConstraint *alignment1103638512 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103638512->addShape(19, 0); + ccs.push_back(alignment1103638512); + + AlignmentConstraint *alignment1103638608 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103638608->addShape(22, 0); + ccs.push_back(alignment1103638608); + + AlignmentConstraint *alignment1095948608 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1095948608->addShape(26, 0); + ccs.push_back(alignment1095948608); + + AlignmentConstraint *alignment1095948704 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1095948704->addShape(30, 0); + ccs.push_back(alignment1095948704); + + AlignmentConstraint *alignment1109826288 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1109826288->addShape(32, 0); + ccs.push_back(alignment1109826288); + + AlignmentConstraint *alignment1109826384 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1109826384->addShape(40, 0); + ccs.push_back(alignment1109826384); + + AlignmentConstraint *alignment1110086352 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1110086352->addShape(41, 0); + ccs.push_back(alignment1110086352); + + AlignmentConstraint *alignment1110086480 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1110086480->addShape(43, 0); + ccs.push_back(alignment1110086480); + + AlignmentConstraint *alignment1100384896 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100384896->addShape(44, 0); + ccs.push_back(alignment1100384896); + + AlignmentConstraint *alignment1100385056 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100385056->addShape(33, 0); + alignment1100385056->addShape(42, 0); + alignment1100385056->addShape(48, 0); + alignment1100385056->addShape(12, 0); + alignment1100385056->addShape(47, 0); + alignment1100385056->addShape(34, 0); + alignment1100385056->addShape(24, 0); + ccs.push_back(alignment1100385056); + + AlignmentConstraint *alignment1114389776 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114389776->addShape(49, 0); + ccs.push_back(alignment1114389776); + + AlignmentConstraint *alignment1114389936 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114389936->addShape(50, 0); + ccs.push_back(alignment1114389936); + + AlignmentConstraint *alignment1103858368 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103858368->addShape(53, 0); + ccs.push_back(alignment1103858368); + + AlignmentConstraint *alignment1103858496 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103858496->addShape(35, 0); + alignment1103858496->addShape(57, 0); + ccs.push_back(alignment1103858496); + + AlignmentConstraint *alignment1103858720 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103858720->addShape(60, 0); + ccs.push_back(alignment1103858720); + + AlignmentConstraint *alignment1103857616 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103857616->addShape(61, 0); + alignment1103857616->addShape(18, 0); + ccs.push_back(alignment1103857616); + + AlignmentConstraint *alignment1103857840 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103857840->addShape(64, 0); + alignment1103857840->addShape(28, 0); + alignment1103857840->addShape(67, 0); + alignment1103857840->addShape(29, 0); + ccs.push_back(alignment1103857840); + + AlignmentConstraint *alignment1103858032 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103858032->addShape(68, 0); + alignment1103858032->addShape(21, 0); + ccs.push_back(alignment1103858032); + + AlignmentConstraint *alignment1103741312 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103741312->addShape(72, 0); + ccs.push_back(alignment1103741312); + + AlignmentConstraint *alignment1103741440 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103741440->addShape(73, 0); + ccs.push_back(alignment1103741440); + + AlignmentConstraint *alignment1103741600 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103741600->addShape(71, 0); + alignment1103741600->addShape(74, 0); + ccs.push_back(alignment1103741600); + + AlignmentConstraint *alignment1103741824 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103741824->addShape(66, 0); + alignment1103741824->addShape(56, 0); + alignment1103741824->addShape(70, 0); + alignment1103741824->addShape(69, 0); + alignment1103741824->addShape(5, 0); + alignment1103741824->addShape(11, 0); + alignment1103741824->addShape(55, 0); + alignment1103741824->addShape(75, 0); + ccs.push_back(alignment1103741824); + + AlignmentConstraint *alignment1103742144 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103742144->addShape(9, 0); + alignment1103742144->addShape(82, 0); + ccs.push_back(alignment1103742144); + + AlignmentConstraint *alignment1103743632 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103743632->addShape(83, 0); + ccs.push_back(alignment1103743632); + + AlignmentConstraint *alignment1113416080 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1113416080->addShape(84, 0); + ccs.push_back(alignment1113416080); + + AlignmentConstraint *alignment1113416240 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1113416240->addShape(81, 0); + alignment1113416240->addShape(85, 0); + alignment1113416240->addShape(86, 0); + ccs.push_back(alignment1113416240); + + AlignmentConstraint *alignment1103744288 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103744288->addShape(87, 0); + alignment1103744288->addShape(89, 0); + alignment1103744288->addShape(58, 0); + alignment1103744288->addShape(65, 0); + ccs.push_back(alignment1103744288); + + AlignmentConstraint *alignment1103744448 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103744448->addShape(79, 0); + alignment1103744448->addShape(59, 0); + alignment1103744448->addShape(90, 0); + alignment1103744448->addShape(25, 0); + alignment1103744448->addShape(20, 0); + ccs.push_back(alignment1103744448); + + AlignmentConstraint *alignment1103744704 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103744704->addShape(80, 0); + alignment1103744704->addShape(91, 0); + alignment1103744704->addShape(63, 0); + alignment1103744704->addShape(31, 0); + alignment1103744704->addShape(78, 0); + alignment1103744704->addShape(36, 0); + ccs.push_back(alignment1103744704); + + AlignmentConstraint *alignment1103744992 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1103744992->addShape(27, 0); + alignment1103744992->addShape(92, 0); + ccs.push_back(alignment1103744992); + + AlignmentConstraint *alignment1114376272 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114376272->addShape(93, 0); + ccs.push_back(alignment1114376272); + + AlignmentConstraint *alignment1114376400 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114376400->addShape(95, 0); + alignment1114376400->addShape(76, 0); + ccs.push_back(alignment1114376400); + + AlignmentConstraint *alignment1114376624 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114376624->addShape(96, 0); + alignment1114376624->addShape(88, 0); + ccs.push_back(alignment1114376624); + + AlignmentConstraint *alignment1114376816 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114376816->addShape(97, 0); + ccs.push_back(alignment1114376816); + + AlignmentConstraint *alignment1114376944 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114376944->addShape(94, 0); + alignment1114376944->addShape(54, 0); + alignment1114376944->addShape(98, 0); + ccs.push_back(alignment1114376944); + + AlignmentConstraint *alignment1114377168 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114377168->addShape(77, 0); + alignment1114377168->addShape(99, 0); + ccs.push_back(alignment1114377168); + + AlignmentConstraint *alignment1114377360 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114377360->addShape(51, 0); + alignment1114377360->addShape(101, 0); + alignment1114377360->addShape(102, 0); + alignment1114377360->addShape(52, 0); + ccs.push_back(alignment1114377360); + + AlignmentConstraint *alignment1114377600 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114377600->addShape(107, 0); + alignment1114377600->addShape(62, 0); + alignment1114377600->addShape(105, 0); + alignment1114377600->addShape(106, 0); + alignment1114377600->addShape(104, 0); + alignment1114377600->addShape(39, 0); + alignment1114377600->addShape(100, 0); + ccs.push_back(alignment1114377600); + + AlignmentConstraint *alignment1114378048 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114378048->addShape(3, 0); + alignment1114378048->addShape(2, 0); + alignment1114378048->addShape(108, 0); + ccs.push_back(alignment1114378048); + + SeparationConstraint *separation1114378272 = new SeparationConstraint(vpsc::XDIM, alignment1103858496, alignment1114376944, 44.3333, false); + ccs.push_back(separation1114378272); + + SeparationConstraint *separation1114378416 = new SeparationConstraint(vpsc::XDIM, alignment1114376944, alignment1113416080, 24.6667, false); + ccs.push_back(separation1114378416); + + SeparationConstraint *separation1114378592 = new SeparationConstraint(vpsc::XDIM, alignment1113416080, alignment1114389776, 11, false); + ccs.push_back(separation1114378592); + + SeparationConstraint *separation1114378768 = new SeparationConstraint(vpsc::XDIM, alignment1114389776, alignment1103858368, 23, false); + ccs.push_back(separation1114378768); + + SeparationConstraint *separation1114378944 = new SeparationConstraint(vpsc::XDIM, alignment1103858368, alignment1109826288, 17, false); + ccs.push_back(separation1114378944); + + SeparationConstraint *separation1114379120 = new SeparationConstraint(vpsc::XDIM, alignment1109826288, alignment1114376816, 6, false); + ccs.push_back(separation1114379120); + + SeparationConstraint *separation1114379296 = new SeparationConstraint(vpsc::XDIM, alignment1114376816, alignment1103856272, 19, false); + ccs.push_back(separation1114379296); + + SeparationConstraint *separation1114379472 = new SeparationConstraint(vpsc::XDIM, alignment1103856272, alignment1103743632, 14, false); + ccs.push_back(separation1114379472); + + SeparationConstraint *separation1114379648 = new SeparationConstraint(vpsc::XDIM, alignment1103743632, alignment1114389936, 4, false); + ccs.push_back(separation1114379648); + + SeparationConstraint *separation1114379824 = new SeparationConstraint(vpsc::XDIM, alignment1114389936, alignment1103741824, 13.75, false); + ccs.push_back(separation1114379824); + + SeparationConstraint *separation1114380000 = new SeparationConstraint(vpsc::XDIM, alignment1103741824, alignment1114376272, 8.25, false); + ccs.push_back(separation1114380000); + + SeparationConstraint *separation1114380176 = new SeparationConstraint(vpsc::XDIM, alignment1114376272, alignment1114376624, 23, false); + ccs.push_back(separation1114380176); + + SeparationConstraint *separation1114380352 = new SeparationConstraint(vpsc::XDIM, alignment1114376624, alignment1103638608, 15, false); + ccs.push_back(separation1114380352); + + SeparationConstraint *separation1114380528 = new SeparationConstraint(vpsc::XDIM, alignment1103638608, alignment1114378048, 6.66667, false); + ccs.push_back(separation1114380528); + + SeparationConstraint *separation1114380704 = new SeparationConstraint(vpsc::XDIM, alignment1114378048, alignment1110086352, 15.3333, false); + ccs.push_back(separation1114380704); + + SeparationConstraint *separation1114380880 = new SeparationConstraint(vpsc::XDIM, alignment1110086352, alignment1110086480, 8, false); + ccs.push_back(separation1114380880); + + SeparationConstraint *separation1114381056 = new SeparationConstraint(vpsc::XDIM, alignment1110086480, alignment1114387328, 5, false); + ccs.push_back(separation1114381056); + + SeparationConstraint *separation1116666144 = new SeparationConstraint(vpsc::XDIM, alignment1114387328, alignment1103858032, 22, false); + ccs.push_back(separation1116666144); + + SeparationConstraint *separation1103743760 = new SeparationConstraint(vpsc::XDIM, alignment1103858032, alignment1103744288, 3, false); + ccs.push_back(separation1103743760); + + SeparationConstraint *separation1103743904 = new SeparationConstraint(vpsc::XDIM, alignment1103744288, alignment1113416240, 6, false); + ccs.push_back(separation1103743904); + + SeparationConstraint *separation1103744080 = new SeparationConstraint(vpsc::XDIM, alignment1113416240, alignment1114377168, 10, false); + ccs.push_back(separation1103744080); + + SeparationConstraint *separation1114381232 = new SeparationConstraint(vpsc::XDIM, alignment1114377168, alignment1103741440, 17, false); + ccs.push_back(separation1114381232); + + SeparationConstraint *separation1114381376 = new SeparationConstraint(vpsc::XDIM, alignment1103741440, alignment1100385056, 29, false); + ccs.push_back(separation1114381376); + + SeparationConstraint *separation1114381552 = new SeparationConstraint(vpsc::XDIM, alignment1100385056, alignment1109826384, 41, false); + ccs.push_back(separation1114381552); + + SeparationConstraint *separation1114381728 = new SeparationConstraint(vpsc::XDIM, alignment1109826384, alignment1114376400, 4, false); + ccs.push_back(separation1114381728); + + SeparationConstraint *separation1114370064 = new SeparationConstraint(vpsc::XDIM, alignment1114376400, alignment1103859296, 3, false); + ccs.push_back(separation1114370064); + + SeparationConstraint *separation1114370240 = new SeparationConstraint(vpsc::XDIM, alignment1103859296, alignment1103742144, 7, false); + ccs.push_back(separation1114370240); + + SeparationConstraint *separation1114370416 = new SeparationConstraint(vpsc::XDIM, alignment1103742144, alignment1102536224, 16, false); + ccs.push_back(separation1114370416); + + SeparationConstraint *separation1114370592 = new SeparationConstraint(vpsc::XDIM, alignment1102536224, alignment1095948608, 16, false); + ccs.push_back(separation1114370592); + + SeparationConstraint *separation1114370768 = new SeparationConstraint(vpsc::XDIM, alignment1095948608, alignment1103741312, 13, false); + ccs.push_back(separation1114370768); + + SeparationConstraint *separation1114370944 = new SeparationConstraint(vpsc::XDIM, alignment1103741312, alignment1103744448, 12, false); + ccs.push_back(separation1114370944); + + SeparationConstraint *separation1114371120 = new SeparationConstraint(vpsc::XDIM, alignment1103744448, alignment1108560576, 16, false); + ccs.push_back(separation1114371120); + + SeparationConstraint *separation1114371296 = new SeparationConstraint(vpsc::XDIM, alignment1108560576, alignment1103744992, 8.5, false); + ccs.push_back(separation1114371296); + + SeparationConstraint *separation1114371472 = new SeparationConstraint(vpsc::XDIM, alignment1103744992, alignment1103858720, 10.5, false); + ccs.push_back(separation1114371472); + + SeparationConstraint *separation1114371648 = new SeparationConstraint(vpsc::XDIM, alignment1103858720, alignment1114377600, 23.7143, false); + ccs.push_back(separation1114371648); + + SeparationConstraint *separation1114371824 = new SeparationConstraint(vpsc::XDIM, alignment1114377600, alignment1102536400, 7.28571, false); + ccs.push_back(separation1114371824); + + SeparationConstraint *separation1114372000 = new SeparationConstraint(vpsc::XDIM, alignment1102536400, alignment1103741600, 49, false); + ccs.push_back(separation1114372000); + + SeparationConstraint *separation1114372176 = new SeparationConstraint(vpsc::XDIM, alignment1103741600, alignment1103638512, 25, false); + ccs.push_back(separation1114372176); + + SeparationConstraint *separation1114372352 = new SeparationConstraint(vpsc::XDIM, alignment1103638512, alignment1113412976, 26, false); + ccs.push_back(separation1114372352); + + SeparationConstraint *separation1114372528 = new SeparationConstraint(vpsc::XDIM, alignment1113412976, alignment1100384896, 7, false); + ccs.push_back(separation1114372528); + + SeparationConstraint *separation1114372704 = new SeparationConstraint(vpsc::XDIM, alignment1100384896, alignment1102857472, 15, false); + ccs.push_back(separation1114372704); + + SeparationConstraint *separation1114372880 = new SeparationConstraint(vpsc::XDIM, alignment1102857472, alignment1103744704, 21.8333, false); + ccs.push_back(separation1114372880); + + SeparationConstraint *separation1114373056 = new SeparationConstraint(vpsc::XDIM, alignment1103744704, alignment1103856000, 21.1667, false); + ccs.push_back(separation1114373056); + + SeparationConstraint *separation1114373232 = new SeparationConstraint(vpsc::XDIM, alignment1103856000, alignment1095948704, 17, false); + ccs.push_back(separation1114373232); + + SeparationConstraint *separation1114373408 = new SeparationConstraint(vpsc::XDIM, alignment1095948704, alignment1103857616, 17.5, false); + ccs.push_back(separation1114373408); + + SeparationConstraint *separation1114373584 = new SeparationConstraint(vpsc::XDIM, alignment1103857616, alignment1103857840, 25.75, false); + ccs.push_back(separation1114373584); + + SeparationConstraint *separation1114373760 = new SeparationConstraint(vpsc::XDIM, alignment1103857840, alignment1114377360, 52.25, false); + ccs.push_back(separation1114373760); + + AlignmentConstraint *alignment1114373936 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114373936->addShape(0, 0); + ccs.push_back(alignment1114373936); + + AlignmentConstraint *alignment1114374096 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114374096->addShape(4, 0); + ccs.push_back(alignment1114374096); + + AlignmentConstraint *alignment1114374256 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114374256->addShape(5, 0); + ccs.push_back(alignment1114374256); + + AlignmentConstraint *alignment1114374416 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114374416->addShape(6, 0); + ccs.push_back(alignment1114374416); + + AlignmentConstraint *alignment1114374576 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114374576->addShape(7, 0); + ccs.push_back(alignment1114374576); + + AlignmentConstraint *alignment1114374736 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114374736->addShape(10, 0); + ccs.push_back(alignment1114374736); + + AlignmentConstraint *alignment1114374896 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114374896->addShape(11, 0); + ccs.push_back(alignment1114374896); + + AlignmentConstraint *alignment1114375056 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114375056->addShape(12, 0); + ccs.push_back(alignment1114375056); + + AlignmentConstraint *alignment1114375216 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114375216->addShape(15, 0); + alignment1114375216->addShape(16, 0); + alignment1114375216->addShape(14, 0); + ccs.push_back(alignment1114375216); + + AlignmentConstraint *alignment1114375488 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114375488->addShape(17, 0); + ccs.push_back(alignment1114375488); + + AlignmentConstraint *alignment1114375616 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114375616->addShape(26, 0); + alignment1114375616->addShape(27, 0); + ccs.push_back(alignment1114375616); + + AlignmentConstraint *alignment1114375840 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114375840->addShape(28, 0); + alignment1114375840->addShape(20, 0); + ccs.push_back(alignment1114375840); + + AlignmentConstraint *alignment1114429984 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114429984->addShape(31, 0); + ccs.push_back(alignment1114429984); + + AlignmentConstraint *alignment1114430112 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114430112->addShape(32, 0); + ccs.push_back(alignment1114430112); + + AlignmentConstraint *alignment1114430272 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114430272->addShape(33, 0); + ccs.push_back(alignment1114430272); + + AlignmentConstraint *alignment1114430432 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114430432->addShape(35, 0); + ccs.push_back(alignment1114430432); + + AlignmentConstraint *alignment1114430592 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114430592->addShape(36, 0); + ccs.push_back(alignment1114430592); + + AlignmentConstraint *alignment1114430752 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114430752->addShape(51, 0); + alignment1114430752->addShape(29, 0); + ccs.push_back(alignment1114430752); + + AlignmentConstraint *alignment1114430976 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114430976->addShape(52, 0); + ccs.push_back(alignment1114430976); + + AlignmentConstraint *alignment1114431104 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114431104->addShape(55, 0); + alignment1114431104->addShape(2, 0); + ccs.push_back(alignment1114431104); + + AlignmentConstraint *alignment1114431328 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114431328->addShape(61, 0); + alignment1114431328->addShape(60, 0); + alignment1114431328->addShape(8, 0); + ccs.push_back(alignment1114431328); + + AlignmentConstraint *alignment1114431568 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114431568->addShape(66, 0); + alignment1114431568->addShape(21, 0); + ccs.push_back(alignment1114431568); + + AlignmentConstraint *alignment1114431760 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114431760->addShape(67, 0); + ccs.push_back(alignment1114431760); + + AlignmentConstraint *alignment1114431888 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114431888->addShape(70, 0); + ccs.push_back(alignment1114431888); + + AlignmentConstraint *alignment1114432048 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114432048->addShape(71, 0); + alignment1114432048->addShape(73, 0); + alignment1114432048->addShape(40, 0); + alignment1114432048->addShape(72, 0); + alignment1114432048->addShape(41, 0); + alignment1114432048->addShape(39, 0); + ccs.push_back(alignment1114432048); + + AlignmentConstraint *alignment1114432464 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114432464->addShape(78, 0); + alignment1114432464->addShape(75, 0); + alignment1114432464->addShape(34, 0); + ccs.push_back(alignment1114432464); + + AlignmentConstraint *alignment1114432688 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114432688->addShape(13, 0); + alignment1114432688->addShape(19, 0); + alignment1114432688->addShape(58, 0); + alignment1114432688->addShape(80, 0); + alignment1114432688->addShape(59, 0); + ccs.push_back(alignment1114432688); + + AlignmentConstraint *alignment1114433040 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114433040->addShape(85, 0); + ccs.push_back(alignment1114433040); + + AlignmentConstraint *alignment1114433200 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114433200->addShape(86, 0); + ccs.push_back(alignment1114433200); + + AlignmentConstraint *alignment1114433360 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114433360->addShape(87, 0); + alignment1114433360->addShape(9, 0); + alignment1114433360->addShape(62, 0); + alignment1114433360->addShape(63, 0); + alignment1114433360->addShape(57, 0); + ccs.push_back(alignment1114433360); + + AlignmentConstraint *alignment1114433696 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114433696->addShape(56, 0); + alignment1114433696->addShape(3, 0); + alignment1114433696->addShape(89, 0); + ccs.push_back(alignment1114433696); + + AlignmentConstraint *alignment1114433920 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114433920->addShape(65, 0); + alignment1114433920->addShape(48, 0); + alignment1114433920->addShape(30, 0); + alignment1114433920->addShape(90, 0); + alignment1114433920->addShape(44, 0); + ccs.push_back(alignment1114433920); + + AlignmentConstraint *alignment1114434272 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114434272->addShape(91, 0); + alignment1114434272->addShape(25, 0); + ccs.push_back(alignment1114434272); + + AlignmentConstraint *alignment1114434496 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114434496->addShape(68, 0); + alignment1114434496->addShape(94, 0); + alignment1114434496->addShape(83, 0); + alignment1114434496->addShape(22, 0); + alignment1114434496->addShape(53, 0); + alignment1114434496->addShape(24, 0); + alignment1114434496->addShape(82, 0); + ccs.push_back(alignment1114434496); + + AlignmentConstraint *alignment1114436928 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114436928->addShape(97, 0); + alignment1114436928->addShape(43, 0); + alignment1114436928->addShape(49, 0); + alignment1114436928->addShape(77, 0); + alignment1114436928->addShape(42, 0); + alignment1114436928->addShape(74, 0); + alignment1114436928->addShape(76, 0); + alignment1114436928->addShape(50, 0); + alignment1114436928->addShape(88, 0); + alignment1114436928->addShape(92, 0); + alignment1114436928->addShape(98, 0); + ccs.push_back(alignment1114436928); + + AlignmentConstraint *alignment1114369232 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114369232->addShape(96, 0); + alignment1114369232->addShape(95, 0); + alignment1114369232->addShape(99, 0); + alignment1114369232->addShape(54, 0); + ccs.push_back(alignment1114369232); + + AlignmentConstraint *alignment1114369456 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114369456->addShape(100, 0); + ccs.push_back(alignment1114369456); + + AlignmentConstraint *alignment1114369616 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114369616->addShape(81, 0); + alignment1114369616->addShape(101, 0); + alignment1114369616->addShape(69, 0); + alignment1114369616->addShape(79, 0); + alignment1114369616->addShape(64, 0); + alignment1114369616->addShape(47, 0); + alignment1114369616->addShape(84, 0); + ccs.push_back(alignment1114369616); + + AlignmentConstraint *alignment1114437392 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114437392->addShape(104, 0); + ccs.push_back(alignment1114437392); + + AlignmentConstraint *alignment1100848528 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100848528->addShape(102, 0); + alignment1100848528->addShape(105, 0); + ccs.push_back(alignment1100848528); + + AlignmentConstraint *alignment1100848752 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100848752->addShape(106, 0); + ccs.push_back(alignment1100848752); + + AlignmentConstraint *alignment1100848880 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100848880->addShape(107, 0); + ccs.push_back(alignment1100848880); + + AlignmentConstraint *alignment1100849040 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100849040->addShape(18, 0); + alignment1100849040->addShape(93, 0); + alignment1100849040->addShape(108, 0); + ccs.push_back(alignment1100849040); + + SeparationConstraint *separation1100849264 = new SeparationConstraint(vpsc::YDIM, alignment1114431104, alignment1114433696, 30.1667, false); + ccs.push_back(separation1100849264); + + SeparationConstraint *separation1100849360 = new SeparationConstraint(vpsc::YDIM, alignment1114433696, alignment1114374576, 8.33333, false); + ccs.push_back(separation1100849360); + + SeparationConstraint *separation1100849536 = new SeparationConstraint(vpsc::YDIM, alignment1114374576, alignment1114431328, 18.3333, false); + ccs.push_back(separation1100849536); + + SeparationConstraint *separation1100849712 = new SeparationConstraint(vpsc::YDIM, alignment1114431328, alignment1114374736, 6.66667, false); + ccs.push_back(separation1100849712); + + SeparationConstraint *separation1100849888 = new SeparationConstraint(vpsc::YDIM, alignment1114374736, alignment1114374096, 3, false); + ccs.push_back(separation1100849888); + + SeparationConstraint *separation1100850064 = new SeparationConstraint(vpsc::YDIM, alignment1114374096, alignment1114374256, 3, false); + ccs.push_back(separation1100850064); + + SeparationConstraint *separation1100850240 = new SeparationConstraint(vpsc::YDIM, alignment1114374256, alignment1114374416, 23, false); + ccs.push_back(separation1100850240); + + SeparationConstraint *separation1100850416 = new SeparationConstraint(vpsc::YDIM, alignment1114374416, alignment1114433360, 11.6, false); + ccs.push_back(separation1100850416); + + SeparationConstraint *separation1100850592 = new SeparationConstraint(vpsc::YDIM, alignment1114433360, alignment1114373936, 9.4, false); + ccs.push_back(separation1100850592); + + SeparationConstraint *separation1100850768 = new SeparationConstraint(vpsc::YDIM, alignment1114373936, alignment1100849040, 18.6667, false); + ccs.push_back(separation1100850768); + + SeparationConstraint *separation1100850944 = new SeparationConstraint(vpsc::YDIM, alignment1100849040, alignment1114375216, 14.6667, false); + ccs.push_back(separation1100850944); + + SeparationConstraint *separation1100851120 = new SeparationConstraint(vpsc::YDIM, alignment1114375216, alignment1114375488, 19.6667, false); + ccs.push_back(separation1100851120); + + SeparationConstraint *separation1100851296 = new SeparationConstraint(vpsc::YDIM, alignment1114375488, alignment1114375056, 32, false); + ccs.push_back(separation1100851296); + + SeparationConstraint *separation1100851472 = new SeparationConstraint(vpsc::YDIM, alignment1114375056, alignment1114432688, 10.8, false); + ccs.push_back(separation1100851472); + + SeparationConstraint *separation1100851648 = new SeparationConstraint(vpsc::YDIM, alignment1114432688, alignment1114369456, 26.2, false); + ccs.push_back(separation1100851648); + + SeparationConstraint *separation1100851824 = new SeparationConstraint(vpsc::YDIM, alignment1114369456, alignment1114375840, 7.5, false); + ccs.push_back(separation1100851824); + + SeparationConstraint *separation1100852000 = new SeparationConstraint(vpsc::YDIM, alignment1114375840, alignment1114374896, 15.5, false); + ccs.push_back(separation1100852000); + + SeparationConstraint *separation1100852176 = new SeparationConstraint(vpsc::YDIM, alignment1114374896, alignment1114433920, 18.4, false); + ccs.push_back(separation1100852176); + + SeparationConstraint *separation1100852352 = new SeparationConstraint(vpsc::YDIM, alignment1114433920, alignment1114431760, 4.6, false); + ccs.push_back(separation1100852352); + + SeparationConstraint *separation1100852528 = new SeparationConstraint(vpsc::YDIM, alignment1114431760, alignment1114429984, 25, false); + ccs.push_back(separation1100852528); + + SeparationConstraint *separation1100852704 = new SeparationConstraint(vpsc::YDIM, alignment1114429984, alignment1114431568, 4.5, false); + ccs.push_back(separation1100852704); + + SeparationConstraint *separation1100852880 = new SeparationConstraint(vpsc::YDIM, alignment1114431568, alignment1114375616, 3.5, false); + ccs.push_back(separation1100852880); + + SeparationConstraint *separation1100853056 = new SeparationConstraint(vpsc::YDIM, alignment1114375616, alignment1114430752, 8, false); + ccs.push_back(separation1100853056); + + SeparationConstraint *separation1100853232 = new SeparationConstraint(vpsc::YDIM, alignment1114430752, alignment1114430112, 29, false); + ccs.push_back(separation1100853232); + + SeparationConstraint *separation1100853408 = new SeparationConstraint(vpsc::YDIM, alignment1114430112, alignment1114369616, 10.1429, false); + ccs.push_back(separation1100853408); + + SeparationConstraint *separation1100853584 = new SeparationConstraint(vpsc::YDIM, alignment1114369616, alignment1114433040, 24.8571, false); + ccs.push_back(separation1100853584); + + SeparationConstraint *separation1100853760 = new SeparationConstraint(vpsc::YDIM, alignment1114433040, alignment1114437392, 14, false); + ccs.push_back(separation1100853760); + + SeparationConstraint *separation1100853936 = new SeparationConstraint(vpsc::YDIM, alignment1114437392, alignment1114430976, 4, false); + ccs.push_back(separation1100853936); + + SeparationConstraint *separation1100854112 = new SeparationConstraint(vpsc::YDIM, alignment1114430976, alignment1114434272, 6.5, false); + ccs.push_back(separation1100854112); + + SeparationConstraint *separation1100854288 = new SeparationConstraint(vpsc::YDIM, alignment1114434272, alignment1114433200, 9.5, false); + ccs.push_back(separation1100854288); + + SeparationConstraint *separation1100854464 = new SeparationConstraint(vpsc::YDIM, alignment1114433200, alignment1100848528, 25, false); + ccs.push_back(separation1100854464); + + SeparationConstraint *separation1100854640 = new SeparationConstraint(vpsc::YDIM, alignment1100848528, alignment1114434496, 9.42857, false); + ccs.push_back(separation1100854640); + + SeparationConstraint *separation1100854816 = new SeparationConstraint(vpsc::YDIM, alignment1114434496, alignment1100848880, 23.5714, false); + ccs.push_back(separation1100854816); + + SeparationConstraint *separation1100854992 = new SeparationConstraint(vpsc::YDIM, alignment1100848880, alignment1100848752, 43, false); + ccs.push_back(separation1100854992); + + SeparationConstraint *separation1100855168 = new SeparationConstraint(vpsc::YDIM, alignment1100848752, alignment1114369232, 8.25, false); + ccs.push_back(separation1100855168); + + SeparationConstraint *separation1100855344 = new SeparationConstraint(vpsc::YDIM, alignment1114369232, alignment1114430592, 33.75, false); + ccs.push_back(separation1100855344); + + SeparationConstraint *separation1100855520 = new SeparationConstraint(vpsc::YDIM, alignment1114430592, alignment1114436928, 36.3636, false); + ccs.push_back(separation1100855520); + + SeparationConstraint *separation1100855696 = new SeparationConstraint(vpsc::YDIM, alignment1114436928, alignment1114432048, 54.1364, false); + ccs.push_back(separation1100855696); + + SeparationConstraint *separation1100855872 = new SeparationConstraint(vpsc::YDIM, alignment1114432048, alignment1114430272, 40.5, false); + ccs.push_back(separation1100855872); + + SeparationConstraint *separation1100856048 = new SeparationConstraint(vpsc::YDIM, alignment1114430272, alignment1114430432, 25, false); + ccs.push_back(separation1100856048); + + SeparationConstraint *separation1100856224 = new SeparationConstraint(vpsc::YDIM, alignment1114430432, alignment1114432464, 17, false); + ccs.push_back(separation1100856224); + + SeparationConstraint *separation1100856400 = new SeparationConstraint(vpsc::YDIM, alignment1114432464, alignment1114431888, 33, false); + ccs.push_back(separation1100856400); + + AlignmentConstraint *alignment1100856576 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100856576->addShape(0, 0); + alignment1100856576->addShape(109, 0); + ccs.push_back(alignment1100856576); + + SeparationConstraint *separation1100856800 = new SeparationConstraint(vpsc::YDIM, 0, 109, 50, true); + ccs.push_back(separation1100856800); + + AlignmentConstraint *alignment1100856944 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100856944->addShape(2, 0); + alignment1100856944->addShape(110, 0); + ccs.push_back(alignment1100856944); + + SeparationConstraint *separation1100857168 = new SeparationConstraint(vpsc::YDIM, 2, 110, -50, true); + ccs.push_back(separation1100857168); + + AlignmentConstraint *alignment1100857312 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100857312->addShape(3, 0); + alignment1100857312->addShape(111, 0); + ccs.push_back(alignment1100857312); + + SeparationConstraint *separation1100857536 = new SeparationConstraint(vpsc::YDIM, 3, 111, -50, true); + ccs.push_back(separation1100857536); + + AlignmentConstraint *alignment1100857680 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100857680->addShape(4, 0); + alignment1100857680->addShape(112, 0); + ccs.push_back(alignment1100857680); + + SeparationConstraint *separation1100857904 = new SeparationConstraint(vpsc::XDIM, 4, 112, -62, true); + ccs.push_back(separation1100857904); + + AlignmentConstraint *alignment1100858048 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100858048->addShape(5, 0); + alignment1100858048->addShape(113, 0); + ccs.push_back(alignment1100858048); + + SeparationConstraint *separation1100858272 = new SeparationConstraint(vpsc::XDIM, 5, 113, 62, true); + ccs.push_back(separation1100858272); + + AlignmentConstraint *alignment1100858416 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100858416->addShape(6, 0); + alignment1100858416->addShape(114, 0); + ccs.push_back(alignment1100858416); + + SeparationConstraint *separation1100858640 = new SeparationConstraint(vpsc::YDIM, 6, 114, -50, true); + ccs.push_back(separation1100858640); + + AlignmentConstraint *alignment1100858784 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100858784->addShape(7, 0); + alignment1100858784->addShape(115, 0); + ccs.push_back(alignment1100858784); + + SeparationConstraint *separation1100859008 = new SeparationConstraint(vpsc::YDIM, 7, 115, -50, true); + ccs.push_back(separation1100859008); + + AlignmentConstraint *alignment1100859152 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100859152->addShape(8, 0); + alignment1100859152->addShape(116, 0); + ccs.push_back(alignment1100859152); + + SeparationConstraint *separation1100859376 = new SeparationConstraint(vpsc::YDIM, 8, 116, -50, true); + ccs.push_back(separation1100859376); + + AlignmentConstraint *alignment1100859520 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100859520->addShape(9, 0); + alignment1100859520->addShape(117, 0); + ccs.push_back(alignment1100859520); + + SeparationConstraint *separation1100859744 = new SeparationConstraint(vpsc::YDIM, 9, 117, -50, true); + ccs.push_back(separation1100859744); + + AlignmentConstraint *alignment1100859888 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100859888->addShape(10, 0); + alignment1100859888->addShape(118, 0); + ccs.push_back(alignment1100859888); + + SeparationConstraint *separation1100860112 = new SeparationConstraint(vpsc::YDIM, 10, 118, 50, true); + ccs.push_back(separation1100860112); + + AlignmentConstraint *alignment1100860256 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100860256->addShape(11, 0); + alignment1100860256->addShape(119, 0); + ccs.push_back(alignment1100860256); + + SeparationConstraint *separation1100860480 = new SeparationConstraint(vpsc::YDIM, 11, 119, -50, true); + ccs.push_back(separation1100860480); + + AlignmentConstraint *alignment1100860624 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100860624->addShape(12, 0); + alignment1100860624->addShape(120, 0); + ccs.push_back(alignment1100860624); + + SeparationConstraint *separation1100860848 = new SeparationConstraint(vpsc::YDIM, 12, 120, -50, true); + ccs.push_back(separation1100860848); + + AlignmentConstraint *alignment1100860992 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100860992->addShape(13, 0); + alignment1100860992->addShape(121, 0); + ccs.push_back(alignment1100860992); + + SeparationConstraint *separation1100861216 = new SeparationConstraint(vpsc::YDIM, 13, 121, -50, true); + ccs.push_back(separation1100861216); + + AlignmentConstraint *alignment1100861360 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100861360->addShape(14, 0); + alignment1100861360->addShape(122, 0); + ccs.push_back(alignment1100861360); + + SeparationConstraint *separation1100861584 = new SeparationConstraint(vpsc::YDIM, 14, 122, -50, true); + ccs.push_back(separation1100861584); + + AlignmentConstraint *alignment1100861728 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100861728->addShape(15, 0); + alignment1100861728->addShape(123, 0); + ccs.push_back(alignment1100861728); + + SeparationConstraint *separation1100861952 = new SeparationConstraint(vpsc::YDIM, 15, 123, -50, true); + ccs.push_back(separation1100861952); + + AlignmentConstraint *alignment1100862096 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100862096->addShape(16, 0); + alignment1100862096->addShape(124, 0); + ccs.push_back(alignment1100862096); + + SeparationConstraint *separation1100862320 = new SeparationConstraint(vpsc::XDIM, 16, 124, -62, true); + ccs.push_back(separation1100862320); + + AlignmentConstraint *alignment1100862464 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100862464->addShape(17, 0); + alignment1100862464->addShape(125, 0); + ccs.push_back(alignment1100862464); + + SeparationConstraint *separation1100862688 = new SeparationConstraint(vpsc::XDIM, 17, 125, 62, true); + ccs.push_back(separation1100862688); + + AlignmentConstraint *alignment1100862832 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100862832->addShape(18, 0); + alignment1100862832->addShape(126, 0); + ccs.push_back(alignment1100862832); + + SeparationConstraint *separation1100863056 = new SeparationConstraint(vpsc::XDIM, 18, 126, 62, true); + ccs.push_back(separation1100863056); + + AlignmentConstraint *alignment1100863200 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100863200->addShape(19, 0); + alignment1100863200->addShape(127, 0); + ccs.push_back(alignment1100863200); + + SeparationConstraint *separation1100863424 = new SeparationConstraint(vpsc::YDIM, 19, 127, 50, true); + ccs.push_back(separation1100863424); + + AlignmentConstraint *alignment1100863568 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100863568->addShape(20, 0); + alignment1100863568->addShape(128, 0); + ccs.push_back(alignment1100863568); + + SeparationConstraint *separation1100863792 = new SeparationConstraint(vpsc::XDIM, 20, 128, 62, true); + ccs.push_back(separation1100863792); + + AlignmentConstraint *alignment1100863936 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100863936->addShape(21, 0); + alignment1100863936->addShape(129, 0); + ccs.push_back(alignment1100863936); + + SeparationConstraint *separation1100864160 = new SeparationConstraint(vpsc::YDIM, 21, 129, -50, true); + ccs.push_back(separation1100864160); + + AlignmentConstraint *alignment1100864304 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100864304->addShape(22, 0); + alignment1100864304->addShape(130, 0); + ccs.push_back(alignment1100864304); + + SeparationConstraint *separation1100864528 = new SeparationConstraint(vpsc::YDIM, 22, 130, -50, true); + ccs.push_back(separation1100864528); + + AlignmentConstraint *alignment1100864672 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100864672->addShape(24, 0); + alignment1100864672->addShape(131, 0); + ccs.push_back(alignment1100864672); + + SeparationConstraint *separation1100864896 = new SeparationConstraint(vpsc::YDIM, 24, 131, -50, true); + ccs.push_back(separation1100864896); + + AlignmentConstraint *alignment1100865040 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100865040->addShape(25, 0); + alignment1100865040->addShape(132, 0); + ccs.push_back(alignment1100865040); + + SeparationConstraint *separation1100865264 = new SeparationConstraint(vpsc::YDIM, 25, 132, -50, true); + ccs.push_back(separation1100865264); + + AlignmentConstraint *alignment1100865408 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100865408->addShape(26, 0); + alignment1100865408->addShape(133, 0); + ccs.push_back(alignment1100865408); + + SeparationConstraint *separation1100865632 = new SeparationConstraint(vpsc::XDIM, 26, 133, -62, true); + ccs.push_back(separation1100865632); + + AlignmentConstraint *alignment1100865776 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100865776->addShape(27, 0); + alignment1100865776->addShape(134, 0); + ccs.push_back(alignment1100865776); + + SeparationConstraint *separation1100866000 = new SeparationConstraint(vpsc::XDIM, 27, 134, 62, true); + ccs.push_back(separation1100866000); + + AlignmentConstraint *alignment1100866144 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100866144->addShape(28, 0); + alignment1100866144->addShape(135, 0); + ccs.push_back(alignment1100866144); + + SeparationConstraint *separation1100866368 = new SeparationConstraint(vpsc::XDIM, 28, 135, 62, true); + ccs.push_back(separation1100866368); + + AlignmentConstraint *alignment1100866512 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100866512->addShape(29, 0); + alignment1100866512->addShape(136, 0); + ccs.push_back(alignment1100866512); + + SeparationConstraint *separation1100866736 = new SeparationConstraint(vpsc::XDIM, 29, 136, 62, true); + ccs.push_back(separation1100866736); + + AlignmentConstraint *alignment1100866880 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100866880->addShape(30, 0); + alignment1100866880->addShape(137, 0); + ccs.push_back(alignment1100866880); + + SeparationConstraint *separation1100867104 = new SeparationConstraint(vpsc::XDIM, 30, 137, 62, true); + ccs.push_back(separation1100867104); + + AlignmentConstraint *alignment1100867248 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100867248->addShape(31, 0); + alignment1100867248->addShape(138, 0); + ccs.push_back(alignment1100867248); + + SeparationConstraint *separation1100867472 = new SeparationConstraint(vpsc::XDIM, 31, 138, 62, true); + ccs.push_back(separation1100867472); + + AlignmentConstraint *alignment1100867616 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100867616->addShape(32, 0); + alignment1100867616->addShape(139, 0); + ccs.push_back(alignment1100867616); + + SeparationConstraint *separation1100867840 = new SeparationConstraint(vpsc::YDIM, 32, 139, -50, true); + ccs.push_back(separation1100867840); + + AlignmentConstraint *alignment1100867984 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100867984->addShape(33, 0); + alignment1100867984->addShape(140, 0); + ccs.push_back(alignment1100867984); + + SeparationConstraint *separation1100868208 = new SeparationConstraint(vpsc::YDIM, 33, 140, 50, true); + ccs.push_back(separation1100868208); + + AlignmentConstraint *alignment1100868352 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100868352->addShape(34, 0); + alignment1100868352->addShape(141, 0); + ccs.push_back(alignment1100868352); + + SeparationConstraint *separation1100868576 = new SeparationConstraint(vpsc::YDIM, 34, 141, -50, true); + ccs.push_back(separation1100868576); + + AlignmentConstraint *alignment1100868720 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100868720->addShape(35, 0); + alignment1100868720->addShape(142, 0); + ccs.push_back(alignment1100868720); + + SeparationConstraint *separation1100868944 = new SeparationConstraint(vpsc::XDIM, 35, 142, 62, true); + ccs.push_back(separation1100868944); + + AlignmentConstraint *alignment1100869088 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100869088->addShape(36, 0); + alignment1100869088->addShape(143, 0); + ccs.push_back(alignment1100869088); + + SeparationConstraint *separation1100869312 = new SeparationConstraint(vpsc::XDIM, 36, 143, 62, true); + ccs.push_back(separation1100869312); + + AlignmentConstraint *alignment1100869456 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100869456->addShape(39, 0); + alignment1100869456->addShape(144, 0); + ccs.push_back(alignment1100869456); + + SeparationConstraint *separation1100869680 = new SeparationConstraint(vpsc::YDIM, 39, 144, -50, true); + ccs.push_back(separation1100869680); + + AlignmentConstraint *alignment1100869824 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100869824->addShape(40, 0); + alignment1100869824->addShape(145, 0); + ccs.push_back(alignment1100869824); + + SeparationConstraint *separation1100870048 = new SeparationConstraint(vpsc::YDIM, 40, 145, -50, true); + ccs.push_back(separation1100870048); + + AlignmentConstraint *alignment1100870192 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100870192->addShape(41, 0); + alignment1100870192->addShape(146, 0); + ccs.push_back(alignment1100870192); + + SeparationConstraint *separation1100870416 = new SeparationConstraint(vpsc::XDIM, 41, 146, 62, true); + ccs.push_back(separation1100870416); + + AlignmentConstraint *alignment1100870560 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100870560->addShape(42, 0); + alignment1100870560->addShape(147, 0); + ccs.push_back(alignment1100870560); + + SeparationConstraint *separation1100870784 = new SeparationConstraint(vpsc::YDIM, 42, 147, -50, true); + ccs.push_back(separation1100870784); + + AlignmentConstraint *alignment1114434864 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114434864->addShape(43, 0); + alignment1114434864->addShape(148, 0); + ccs.push_back(alignment1114434864); + + SeparationConstraint *separation1114435088 = new SeparationConstraint(vpsc::YDIM, 43, 148, -50, true); + ccs.push_back(separation1114435088); + + AlignmentConstraint *alignment1114435232 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1114435232->addShape(44, 0); + alignment1114435232->addShape(149, 0); + ccs.push_back(alignment1114435232); + + SeparationConstraint *separation1114435456 = new SeparationConstraint(vpsc::XDIM, 44, 149, -62, true); + ccs.push_back(separation1114435456); + + AlignmentConstraint *alignment1114435600 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114435600->addShape(47, 0); + alignment1114435600->addShape(150, 0); + ccs.push_back(alignment1114435600); + + SeparationConstraint *separation1114435824 = new SeparationConstraint(vpsc::YDIM, 47, 150, -50, true); + ccs.push_back(separation1114435824); + + AlignmentConstraint *alignment1114435968 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114435968->addShape(48, 0); + alignment1114435968->addShape(151, 0); + ccs.push_back(alignment1114435968); + + SeparationConstraint *separation1114436192 = new SeparationConstraint(vpsc::YDIM, 48, 151, -50, true); + ccs.push_back(separation1114436192); + + AlignmentConstraint *alignment1114436336 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114436336->addShape(49, 0); + alignment1114436336->addShape(152, 0); + ccs.push_back(alignment1114436336); + + SeparationConstraint *separation1114436560 = new SeparationConstraint(vpsc::YDIM, 49, 152, -50, true); + ccs.push_back(separation1114436560); + + AlignmentConstraint *alignment1114436704 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1114436704->addShape(50, 0); + alignment1114436704->addShape(153, 0); + ccs.push_back(alignment1114436704); + + SeparationConstraint *separation1100875040 = new SeparationConstraint(vpsc::YDIM, 50, 153, -50, true); + ccs.push_back(separation1100875040); + + AlignmentConstraint *alignment1100875184 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100875184->addShape(51, 0); + alignment1100875184->addShape(154, 0); + ccs.push_back(alignment1100875184); + + SeparationConstraint *separation1100875408 = new SeparationConstraint(vpsc::XDIM, 51, 154, 62, true); + ccs.push_back(separation1100875408); + + AlignmentConstraint *alignment1100875552 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100875552->addShape(52, 0); + alignment1100875552->addShape(155, 0); + ccs.push_back(alignment1100875552); + + SeparationConstraint *separation1100875776 = new SeparationConstraint(vpsc::XDIM, 52, 155, 62, true); + ccs.push_back(separation1100875776); + + AlignmentConstraint *alignment1100875920 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100875920->addShape(53, 0); + alignment1100875920->addShape(156, 0); + ccs.push_back(alignment1100875920); + + SeparationConstraint *separation1100876144 = new SeparationConstraint(vpsc::YDIM, 53, 156, -50, true); + ccs.push_back(separation1100876144); + + AlignmentConstraint *alignment1100876288 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100876288->addShape(54, 0); + alignment1100876288->addShape(157, 0); + ccs.push_back(alignment1100876288); + + SeparationConstraint *separation1100876512 = new SeparationConstraint(vpsc::XDIM, 54, 157, 62, true); + ccs.push_back(separation1100876512); + + AlignmentConstraint *alignment1100876656 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100876656->addShape(104, 0); + alignment1100876656->addShape(158, 0); + ccs.push_back(alignment1100876656); + + SeparationConstraint *separation1100876880 = new SeparationConstraint(vpsc::XDIM, 104, 158, 62, true); + ccs.push_back(separation1100876880); + + AlignmentConstraint *alignment1100877024 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment1100877024->addShape(107, 0); + alignment1100877024->addShape(159, 0); + ccs.push_back(alignment1100877024); + + SeparationConstraint *separation1100877248 = new SeparationConstraint(vpsc::XDIM, 107, 159, 62, true); + ccs.push_back(separation1100877248); + + AlignmentConstraint *alignment1100877392 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment1100877392->addShape(108, 0); + alignment1100877392->addShape(160, 0); + ccs.push_back(alignment1100877392); + + SeparationConstraint *separation1100877616 = new SeparationConstraint(vpsc::YDIM, 108, 160, -50, true); + ccs.push_back(separation1100877616); + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength); + alg.setAvoidNodeOverlaps(true); + RootCluster *cluster1100877760 = new RootCluster(); + cluster1100877760->addChildNode(0); + cluster1100877760->addChildNode(2); + cluster1100877760->addChildNode(3); + cluster1100877760->addChildNode(4); + cluster1100877760->addChildNode(5); + cluster1100877760->addChildNode(6); + cluster1100877760->addChildNode(7); + cluster1100877760->addChildNode(8); + cluster1100877760->addChildNode(9); + cluster1100877760->addChildNode(10); + cluster1100877760->addChildNode(11); + cluster1100877760->addChildNode(12); + cluster1100877760->addChildNode(13); + cluster1100877760->addChildNode(14); + cluster1100877760->addChildNode(15); + cluster1100877760->addChildNode(16); + cluster1100877760->addChildNode(17); + cluster1100877760->addChildNode(18); + cluster1100877760->addChildNode(19); + cluster1100877760->addChildNode(20); + cluster1100877760->addChildNode(21); + cluster1100877760->addChildNode(22); + cluster1100877760->addChildNode(23); + cluster1100877760->addChildNode(24); + cluster1100877760->addChildNode(25); + cluster1100877760->addChildNode(26); + cluster1100877760->addChildNode(27); + cluster1100877760->addChildNode(28); + cluster1100877760->addChildNode(29); + cluster1100877760->addChildNode(30); + cluster1100877760->addChildNode(31); + cluster1100877760->addChildNode(32); + cluster1100877760->addChildNode(33); + cluster1100877760->addChildNode(34); + cluster1100877760->addChildNode(35); + cluster1100877760->addChildNode(36); + cluster1100877760->addChildNode(39); + cluster1100877760->addChildNode(40); + cluster1100877760->addChildNode(41); + cluster1100877760->addChildNode(42); + cluster1100877760->addChildNode(43); + cluster1100877760->addChildNode(44); + cluster1100877760->addChildNode(47); + cluster1100877760->addChildNode(48); + cluster1100877760->addChildNode(49); + cluster1100877760->addChildNode(50); + cluster1100877760->addChildNode(51); + cluster1100877760->addChildNode(52); + cluster1100877760->addChildNode(53); + cluster1100877760->addChildNode(54); + cluster1100877760->addChildNode(55); + cluster1100877760->addChildNode(56); + cluster1100877760->addChildNode(57); + cluster1100877760->addChildNode(58); + cluster1100877760->addChildNode(59); + cluster1100877760->addChildNode(60); + cluster1100877760->addChildNode(61); + cluster1100877760->addChildNode(62); + cluster1100877760->addChildNode(63); + cluster1100877760->addChildNode(64); + cluster1100877760->addChildNode(65); + cluster1100877760->addChildNode(66); + cluster1100877760->addChildNode(67); + cluster1100877760->addChildNode(68); + cluster1100877760->addChildNode(69); + cluster1100877760->addChildNode(70); + cluster1100877760->addChildNode(71); + cluster1100877760->addChildNode(72); + cluster1100877760->addChildNode(73); + cluster1100877760->addChildNode(74); + cluster1100877760->addChildNode(75); + cluster1100877760->addChildNode(76); + cluster1100877760->addChildNode(77); + cluster1100877760->addChildNode(78); + cluster1100877760->addChildNode(79); + cluster1100877760->addChildNode(80); + cluster1100877760->addChildNode(81); + cluster1100877760->addChildNode(82); + cluster1100877760->addChildNode(83); + cluster1100877760->addChildNode(84); + cluster1100877760->addChildNode(85); + cluster1100877760->addChildNode(86); + cluster1100877760->addChildNode(87); + cluster1100877760->addChildNode(88); + cluster1100877760->addChildNode(89); + cluster1100877760->addChildNode(90); + cluster1100877760->addChildNode(91); + cluster1100877760->addChildNode(92); + cluster1100877760->addChildNode(93); + cluster1100877760->addChildNode(94); + cluster1100877760->addChildNode(95); + cluster1100877760->addChildNode(96); + cluster1100877760->addChildNode(97); + cluster1100877760->addChildNode(98); + cluster1100877760->addChildNode(99); + cluster1100877760->addChildNode(100); + cluster1100877760->addChildNode(101); + cluster1100877760->addChildNode(102); + cluster1100877760->addChildNode(104); + cluster1100877760->addChildNode(105); + cluster1100877760->addChildNode(106); + cluster1100877760->addChildNode(107); + cluster1100877760->addChildNode(108); + cluster1100877760->addChildNode(109); + cluster1100877760->addChildNode(110); + cluster1100877760->addChildNode(111); + cluster1100877760->addChildNode(112); + cluster1100877760->addChildNode(113); + cluster1100877760->addChildNode(114); + cluster1100877760->addChildNode(115); + cluster1100877760->addChildNode(116); + cluster1100877760->addChildNode(117); + cluster1100877760->addChildNode(118); + cluster1100877760->addChildNode(119); + cluster1100877760->addChildNode(120); + cluster1100877760->addChildNode(121); + cluster1100877760->addChildNode(122); + cluster1100877760->addChildNode(123); + cluster1100877760->addChildNode(124); + cluster1100877760->addChildNode(125); + cluster1100877760->addChildNode(126); + cluster1100877760->addChildNode(127); + cluster1100877760->addChildNode(128); + cluster1100877760->addChildNode(129); + cluster1100877760->addChildNode(130); + cluster1100877760->addChildNode(131); + cluster1100877760->addChildNode(132); + cluster1100877760->addChildNode(133); + cluster1100877760->addChildNode(134); + cluster1100877760->addChildNode(135); + cluster1100877760->addChildNode(136); + cluster1100877760->addChildNode(137); + cluster1100877760->addChildNode(138); + cluster1100877760->addChildNode(139); + cluster1100877760->addChildNode(140); + cluster1100877760->addChildNode(141); + cluster1100877760->addChildNode(142); + cluster1100877760->addChildNode(143); + cluster1100877760->addChildNode(144); + cluster1100877760->addChildNode(145); + cluster1100877760->addChildNode(146); + cluster1100877760->addChildNode(147); + cluster1100877760->addChildNode(148); + cluster1100877760->addChildNode(149); + cluster1100877760->addChildNode(150); + cluster1100877760->addChildNode(151); + cluster1100877760->addChildNode(152); + cluster1100877760->addChildNode(153); + cluster1100877760->addChildNode(154); + cluster1100877760->addChildNode(155); + cluster1100877760->addChildNode(156); + cluster1100877760->addChildNode(157); + cluster1100877760->addChildNode(158); + cluster1100877760->addChildNode(159); + cluster1100877760->addChildNode(160); + RectangularCluster *cluster1100878032 = new RectangularCluster(); + cluster1100878032->addChildNode(161); + cluster1100877760->addChildCluster(cluster1100878032); + RectangularCluster *cluster1100878416 = new RectangularCluster(); + cluster1100878416->addChildNode(162); + cluster1100877760->addChildCluster(cluster1100878416); + RectangularCluster *cluster1100878800 = new RectangularCluster(); + cluster1100878800->addChildNode(163); + cluster1100877760->addChildCluster(cluster1100878800); + RectangularCluster *cluster1100879168 = new RectangularCluster(); + cluster1100877760->addChildCluster(cluster1100879168); + RectangularCluster *cluster1100879488 = new RectangularCluster(); + cluster1100879488->addChildNode(164); + cluster1100879488->addChildNode(165); + cluster1100879488->addChildNode(166); + cluster1100879488->addChildNode(167); + cluster1100877760->addChildCluster(cluster1100879488); + RectangularCluster *cluster1100879920 = new RectangularCluster(); + cluster1100879920->addChildNode(168); + cluster1100877760->addChildCluster(cluster1100879920); + alg.setClusterHierarchy(cluster1100877760); + alg.setConstraints(ccs); + alg.makeFeasible(); + alg.run(); + alg.outputInstanceToSVG("test-StillOverlap02"); + alg.freeAssociatedObjects(); + return 0; +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/boundary.cpp b/src/3rdparty/adaptagrams/libcola/tests/boundary.cpp new file mode 100644 index 0000000..18e962d --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/boundary.cpp @@ -0,0 +1,121 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file boundary.cpp + * + * a clustered graph using libtopology to preserve the cluster boundary. + */ +/* +* Authors: +* Tim Dwyer <tgdwyer@gmail.com> +*/ +#include <iostream> +#include <iomanip> +#include <fstream> + +#include <vector> +#include <valarray> +#include <algorithm> +#include <float.h> +#include "graphlayouttest.h" +#include <libtopology/topology_graph.h> +#include <libproject/project.h> +using namespace std; +using namespace topology; + +Node* addNode( Nodes& vs, vpsc::Rectangle* r) { + Node *v = new Node(vs.size(), r); + vs.push_back(v); + return v; +} +void addToPath(EdgePoints& ps, Node *v, EdgePoint::RectIntersect i) { + ps.push_back(new EdgePoint(v,i)); +} +struct SetDesiredPos : public PreIteration { + SetDesiredPos(Locks& locks) : PreIteration(locks) {} +}; +struct Test : TestConvergence { + Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es,const string fname) : TestConvergence(d,i), vs(vs), es(es), fname(fname) {} + bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) { + bool converged= TestConvergence::operator()(new_stress,X,Y); + if(converged) { + cerr << "stress="<<new_stress<<" iteration="<<iterations<<endl; + stringstream ss; + ss << fname << "-" << setfill('0') << setw(3) << iterations << ".svg"; + cerr << "writing file: " << ss.str() << endl; + writeFile(vs,es,ss.str()); + } + return converged; + } + double lastStress; + topology::Nodes& vs; + topology::Edges& es; + const string fname; +}; +void clusterBoundary() { + vector<cola::Edge> es; + vector<vpsc::Rectangle*> rs; + rs.push_back(new vpsc::Rectangle(395,449,155,189)); + rs.push_back(new vpsc::Rectangle(309,363,155,189)); + double idealLength=60; + // set up topology graph + topology::Nodes vs; + for(vector<Rectangle*>::iterator i = rs.begin(); i!=rs.end();++i) { + addNode(vs,*i); + } + Edges tes; + EdgePoints ps; + addToPath(ps,vs[1],EdgePoint::BL); + addToPath(ps,vs[0],EdgePoint::BR); + addToPath(ps,vs[0],EdgePoint::TR); + addToPath(ps,vs[1],EdgePoint::TL); + ps.push_back(ps[0]); + tes.push_back(new topology::Edge(idealLength, ps)); + + writeFile(vs,tes,"boundary-000.svg"); + + Locks locks; + locks.push_back(Lock(0,rs[0]->getCentreX(), rs[0]->getCentreY()+10)); + locks.push_back(Lock(1,rs[1]->getCentreX(), rs[1]->getCentreY())); + SetDesiredPos preIteration(locks); + + Test test(0.00001,100,vs,tes,"boundary"); + cola::ConstrainedFDLayout alg(rs,es,idealLength,nullptr,test,&preIteration); + + alg.setTopology(&vs,&tes); + alg.run(true,true); + double finalStress=alg.computeStress(); + printf("finalStress=%f\n",finalStress); + + //assert(finalStress<1e-5); + for_each(rs.begin(),rs.end(),cola::delete_object()); + for_each(tes.begin(),tes.end(),cola::delete_object()); + for_each(vs.begin(),vs.end(),cola::delete_object()); +} +int main() { + clusterBoundary(); + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/connected_components.cpp b/src/3rdparty/adaptagrams/libcola/tests/connected_components.cpp new file mode 100644 index 0000000..d5df479 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/connected_components.cpp @@ -0,0 +1,69 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <iostream> +#include <vector> +#include <set> +#include <libvpsc/rectangle.h> +#include <libcola/cola.h> +#include <libcola/connected_components.h> +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; + +int main() { + const unsigned V = 7; + unsigned c1[]={0,1,2,3}; + set<unsigned> expected_c1(c1,c1+4); + unsigned c2[]={4,5,6}; + set<unsigned> expected_c2(c2,c2+3); + + Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(3, 2), Edge(1, 3), + Edge(4, 5), Edge(5, 6), Edge(6, 4) }; + const std::size_t E = sizeof(edge_array) / sizeof(Edge); + vector<Edge> es(edge_array,edge_array+E); + vector<Component*> cs; + vpsc::Rectangles rs; + double width=100,height=100; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5)); + } + connectedComponents(rs,es,cs); + set<unsigned> result_c1(cs[0]->node_ids.begin(),cs[0]->node_ids.end()); + set<unsigned> result_c2(cs[1]->node_ids.begin(),cs[1]->node_ids.end()); + assert(expected_c1==result_c1); + assert(expected_c2==result_c2); + for(unsigned i=0;i<cs.size();i++) { + printf("Component %d:\n",i); + for(unsigned j=0;j<cs[i]->edges.size();j++) { + Edge& e=cs[i]->edges[j]; + printf("(%d,%d) ",e.first,e.second); + } + cout << endl; + } + return 0; +} diff --git a/src/3rdparty/adaptagrams/libcola/tests/constrained.cpp b/src/3rdparty/adaptagrams/libcola/tests/constrained.cpp new file mode 100644 index 0000000..20215f7 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/constrained.cpp @@ -0,0 +1,99 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file constrained.cpp + * + * runs constraint layout on a small graph. nodes 0 and 3 are constrained + * to a vertical line + * + * + * Authors: + * Tim Dwyer <tgdwyer@gmail.com> + */ +#include <iostream> + +#include <vector> +#include <algorithm> +#include <float.h> +#include <libcola/cola.h> +#include <libcola/output_svg.h> +inline double getRand(double range) { + return range*rand()/RAND_MAX; +} + +using namespace std; +using namespace cola; +/** +* \brief Determines when to terminate layout of a particular graph based +* on a given relative tolerance. +*/ +int main() { + + const unsigned V = 4; + typedef pair < unsigned, unsigned >Edge; + Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(1, 3) }; + unsigned E = sizeof(edge_array) / sizeof(Edge); + vector<Edge> es(edge_array,edge_array+E); + double width=100; + double height=100; + vector<vpsc::Rectangle*> rs; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5)); + } + CompoundConstraints ccs; + AlignmentConstraint ac(vpsc::XDIM); + ccs.push_back(&ac); + ac.addShape(0,0); + ac.addShape(3,0); + // apply steepest descent layout + ConstrainedFDLayout alg2(rs,es,width/2); + alg2.setConstraints(ccs); + alg2.run(); + assert(alg2.computeStress()<0.0013); + // the following pair of nodes should line-up + assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001); + // reset rectangles to random positions + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs[i]->moveCentre(x,y); + } + // apply scaled majorization layout + ConstrainedMajorizationLayout alg(rs,es,nullptr,width/2); + alg.setConstraints(&ccs); + alg.setScaling(true); + alg.run(); + // the following pair of nodes should line-up + assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001); + cout<<rs[0]->getCentreX()<<","<<rs[3]->getCentreX()<<endl; + OutputFile output(rs,es,nullptr,"constrained.svg"); + output.rects=true; + output.generate(); + + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} diff --git a/src/3rdparty/adaptagrams/libcola/tests/containment.cpp b/src/3rdparty/adaptagrams/libcola/tests/containment.cpp new file mode 100644 index 0000000..488700e --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/containment.cpp @@ -0,0 +1,89 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file containment.cpp + * + * simple test of clustered graph layout + * + * Authors: + * Tim Dwyer <tgdwyer@gmail.com> + */ +#include <iostream> + +#include <map> +#include <vector> +#include <algorithm> +#include <float.h> +#include <iomanip> +#include <libcola/cola.h> +#include <libcola/output_svg.h> +#include "graphlayouttest.h" + +using namespace cola; +using namespace std; + +vector<vpsc::Rectangle*> rs; +vector<Edge> es; +RectangularCluster rc, rd; +RootCluster root; +unsigned iteration=0; + +int main() { + + const unsigned V = 5; + typedef pair < unsigned, unsigned >Edge; + Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(3, 4) }; + const std::size_t E = sizeof(edge_array) / sizeof(Edge); + es.resize(E); + copy(edge_array,edge_array+E,es.begin()); + double width=100; + double height=100; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+20,y,y+15)); + } + + const unsigned c[]={0,4}, d[]={1,2,3}; + unsigned nc=sizeof(c)/sizeof(unsigned), nd=sizeof(d)/sizeof(unsigned); + CheckProgress test(0.0001,100); + ConstrainedMajorizationLayout alg(rs,es,&root,30,nullptr,test); + alg.setScaling(true); + rc.nodes.resize(nc); + copy(c,c+nc,rc.nodes.begin()); + rd.nodes.resize(nd); + copy(d,d+nd,rd.nodes.begin()); + root.clusters.push_back(&rc); + root.clusters.push_back(&rd); + alg.run(); + alg.setAvoidOverlaps(); + alg.run(); + OutputFile of(rs,es,&root,"containment.svg",false,true); + of.generate(); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/containment2.cpp b/src/3rdparty/adaptagrams/libcola/tests/containment2.cpp new file mode 100644 index 0000000..d499ffc --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/containment2.cpp @@ -0,0 +1,157 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file + * Interface between Inkscape code (SPItem) and graphlayout functions. + * Authors: + * Tim Dwyer <tgdwyer@gmail.com> + */ +#include <iostream> + +#include <map> +#include <vector> +#include <algorithm> +#include <float.h> +#include <iomanip> +#include <libcola/cola.h> +#include <libcola/output_svg.h> +#include "graphlayouttest.h" + +using namespace cola; +using namespace std; + +vector<vpsc::Rectangle*> rs; +vector<Edge> es; +RootCluster root; +unsigned iteration=0; + +/** +* \brief Determines when to terminate layout of a particular graph based +* on a given relative tolerance. +*/ +int main() { + + const unsigned V = 19; + const char* labels[]={ + "Hamza Alghamdi", + "Nawaf Alhazmi", + "Marwan Al-Shehhi", + "Mohand Alshehri", + "Ahmed Alghamdi", + "Saeed Alghamdi", + "Salem Alhazmi", + "Hani Hanjour", + "Mohamed Atta", + "Ziad Jarrah", + "Ahmed Al Haznawi", + "Fayez Ahmed", + "Ahmed Alnami", + "Khalid Al-Mihdhar", + "Majed Moqed", + "Abdul Aziz Al-Omari", + "Waleed Alshehri", + "Wail Alshehri", + "Satam Suqami"}; + + typedef pair < unsigned, unsigned >Edge; + Edge edge_array[] = { + Edge(0,1), Edge(0,3), Edge(0,4), Edge(0,5), Edge(0,10), + Edge(1,5), Edge(1,6), Edge(1,7), Edge(1,12), Edge(1,13), + Edge(2,8), Edge(2,9), Edge(2,11), Edge(2,15), + Edge(3,11), + Edge(5,10), Edge(5,12), + Edge(7,13), Edge(7,14), + Edge(8,9), Edge(8,15), + Edge(9,10), + Edge(15,16), + Edge(16,17), Edge(16,18), + Edge(17,18) + }; + double g=10; + CompoundConstraints scy; + scy.push_back(new SeparationConstraint(0,10,g)); + scy.push_back(new SeparationConstraint(0,3,g)); + scy.push_back(new SeparationConstraint(0,4,g)); + scy.push_back(new SeparationConstraint(0,12,g)); + scy.push_back(new SeparationConstraint(0,5,g)); + scy.push_back(new SeparationConstraint(1,12,g)); + scy.push_back(new SeparationConstraint(1,5,g)); + scy.push_back(new SeparationConstraint(1,13,g)); + scy.push_back(new SeparationConstraint(1,6,g)); + scy.push_back(new SeparationConstraint(1,7,g)); + scy.push_back(new SeparationConstraint(2,8,g)); + scy.push_back(new SeparationConstraint(2,9,g)); + scy.push_back(new SeparationConstraint(2,15,g)); + scy.push_back(new SeparationConstraint(2,11,g)); + scy.push_back(new SeparationConstraint(5,12,g)); + scy.push_back(new SeparationConstraint(7,13,g)); + scy.push_back(new SeparationConstraint(7,14,g)); + scy.push_back(new SeparationConstraint(16,17,g)); + scy.push_back(new SeparationConstraint(16,18,g)); + const std::size_t E = sizeof(edge_array) / sizeof(Edge); + es.resize(E); + copy(edge_array,edge_array+E,es.begin()); + double width=100; + double height=100; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+17,y,y+10)); + } + + RectangularCluster c; + c.nodes.push_back(0); + c.nodes.push_back(1); + RectangularCluster d; + d.nodes.push_back(3); + d.nodes.push_back(11); + RectangularCluster e; + e.nodes.push_back(8); + e.nodes.push_back(9); + e.nodes.push_back(10); + e.nodes.push_back(15); + e.nodes.push_back(16); + RectangularCluster f; + f.nodes.push_back(17); + f.nodes.push_back(18); + root.clusters.push_back(&c); + root.clusters.push_back(&d); + root.clusters.push_back(&e); + root.clusters.push_back(&f); + OutputFile of(rs,es,&root,"containment2.svg",true,true); + //of.setLabels(V,labels); + CheckProgress test(0.0001,100); + ConstrainedMajorizationLayout alg(rs,es,&root,30,nullptr,test); + alg.setScaling(false); + //alg.setYSeparationConstraints(&scy); + //alg.run(); + alg.setAvoidOverlaps(); + alg.run(); + of.generate(); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/convex_hull.cpp b/src/3rdparty/adaptagrams/libcola/tests/convex_hull.cpp new file mode 100644 index 0000000..38b6629 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/convex_hull.cpp @@ -0,0 +1,180 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** + * Really basic regression test of convex hull implementation + * declared in libcola/convex_hull.h + */ +#include <valarray> +#include <algorithm> +#include <libcola/convex_hull.h> +#include "graphlayouttest.h" + +#include <string> +#include <iostream> +#include <cairomm/context.h> +#include <cairomm/surface.h> + +/* M_PI is defined in math.h in the case of Microsoft Visual C++ */ +#if defined(_MSC_VER) +#define _USE_MATH_DEFINES +#include <math.h> +#endif +using namespace std; + +typedef vector<unsigned> Hull; +/** + * generates a random set of n points in X and Y. + */ +void randTest(unsigned n, valarray<double>& X, valarray<double>& Y) { + X.resize(n); + Y.resize(n); + srand(time(nullptr)); + for(unsigned i=0;i<n;i++) { + X[i]=getRand(1.); + Y[i]=getRand(1.); + } +} +/** + * generates a set of 8 points (actually the vertices of two rectangles) + * which lineup horizontally. The expected hull are the lower-left and + * top-left corners of the left rectangle and the top-right/lower-right + * corners of the right rectangle. + */ +void tworects(valarray<double>& X, valarray<double>& Y, Hull& expectedHull) { + const unsigned n=8; + X.resize(n); + Y.resize(n); + X[0]=330.011898, Y[0]=203.250425; + X[1]=330.011898, Y[1]=237.250425; + X[2]=276.011898, Y[2]=237.250425; + X[3]=276.011898, Y[3]=203.250425; + X[4]=459.998300, Y[4]=203.250425; + X[5]=459.998300, Y[5]=237.250425; + X[6]=405.998300, Y[6]=237.250425; + X[7]=405.998300, Y[7]=203.250425; + unsigned hull[]={3,4,5,2}; + unsigned m=sizeof(hull)/sizeof(unsigned); + expectedHull.resize(m); + copy(hull,hull+m,expectedHull.begin()); +} + +int drawCairo(const string& fname, + const valarray<double>& X, const valarray<double>& Y, + const Hull& hull); + +int main(int argc, char** argv) { + valarray<double> X, Y; + Hull h,expectedHull; + tworects(X,Y,expectedHull); + hull::convex(X,Y,h); + printf("hull size=%d\n",h.size()); + pair<Hull::iterator,Hull::iterator> r + =mismatch(h.begin(),h.end(),expectedHull.begin()); + assert(r.first==h.end()); + drawCairo("convex_tworects.svg",X,Y,h); + + randTest(20,X,Y); + hull::convex(X,Y,h); + drawCairo("convex_hull_random.svg",X,Y,h); + return 0; +} + +/***********CAIRO CODE***************************************************/ +double width = 600; +double height = 400; +double border=10; +void dot(Cairo::RefPtr<Cairo::Context> & cr, double x, double y) { + cr->arc(x, y, + 2., 0.0, 2.0 * M_PI); + cr->stroke(); +} + +double xcoord(double x) { + return border+x*width; +} +double ycoord(double y) { + return border+y*height; +} +int drawCairo(const string& fname, + const valarray<double>& Xin, const valarray<double>& Yin, + const Hull& hull) { +#ifdef CAIRO_HAS_SVG_SURFACE + unsigned n=Xin.size(); + assert(Yin.size()==n); + + // normalise coords to range 0-1 + valarray<double> X=Xin, Y=Yin; + X-=X.min(); + Y-=Y.min(); + X/=X.max(); + Y/=Y.max(); + + Cairo::RefPtr<Cairo::SvgSurface> surface = + Cairo::SvgSurface::create(fname, width+2*border, height+2*border); + + Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(surface); + + cr->save(); // save the state of the context + cr->set_source_rgba(0.0, 0.0, 0.0, 0.7); + // draw a circle at each coordinate + for(unsigned i=0;i<n;i++) { + dot(cr,xcoord(X[i]),ycoord(Y[i])); + } + + cr->set_source_rgba(0.0, 0.0, 0.0, 0.3); + cr->move_to(xcoord(X[hull[0]]),ycoord(Y[hull[0]])); + for(unsigned i=1;i<hull.size();i++) { + cr->line_to(xcoord(X[hull[i]]),ycoord(Y[hull[i]])); + } + cr->line_to(xcoord(X[hull[0]]),ycoord(Y[hull[0]])); + cr->stroke(); + cr->set_source_rgba(0.0, 0.0, 0.0, 1.); + for(vector<unsigned>::const_iterator i=hull.begin();i!=hull.end();++i) { + unsigned j=*i; + stringstream ss; + ss<<j; + printf("p[%d]=(%f,%f)\n",j,X[j],Y[j]); + cr->move_to(xcoord(X[j]),ycoord(Y[j])); + cr->show_text(ss.str()); + cr->stroke(); + } + cr->restore(); + + cr->show_page(); + + cout << "Wrote SVG file \"" << fname << "\"" << endl; + return 0; + +#else + + cout << "You must compile cairo with SVG support for this example to work." + << endl; + return 1; + +#endif + +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/cycle_detector.cpp b/src/3rdparty/adaptagrams/libcola/tests/cycle_detector.cpp new file mode 100644 index 0000000..3b9a0a4 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/cycle_detector.cpp @@ -0,0 +1,386 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <iostream> +#include <vector> +#include <assert.h> +#include <libcola/cola.h> +#include <libcola/cycle_detector.h> +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; +using namespace cycle_detector; +using vpsc::Rectangle; + +int main() { + CycleDetector *cd; + Edges case_a, case_b, case_c, case_d, case_e, case_f, case_g; + + CyclicEdges *cycles = nullptr; + vector<Rectangle *> rs; + unsigned V; + + // create case A + // case A consists of a basic graph where the start point is a source + cout << endl << "ENTERING CASE A" << endl; + V = 5; + case_a.push_back(Edge(0, 1)); + case_a.push_back(Edge(1, 2)); + case_a.push_back(Edge(2, 3)); + case_a.push_back(Edge(3, 4)); + case_a.push_back(Edge(4, 1)); + + // detect the cycles + cd = new CycleDetector(V, &case_a); + cycles = cd->detect_cycles(); + + if (cycles != nullptr) { + cout << "cycles->size(): " << cycles->size() << endl; + for (unsigned i = 0; i < case_a.size(); i++) { + // print out the cycles + if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_a[i].first << ", " << case_a[i].second << ")" << endl; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); + rs.push_back(new Rectangle(30,30+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,30,30+5)); + + assert(rs.size() == V); + + output_svg(rs, case_a, "cycle_detector_case_a.svg", false, true, cycles); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + delete cycles; + } + else { + cout << "No cycles found" << endl; + } + + // create case B + // case B is the same graph of case A but with more elements + cout << endl << "ENTERING CASE B" << endl; + V = 7; + case_b.push_back(Edge(0, 1)); + case_b.push_back(Edge(1, 2)); + case_b.push_back(Edge(2, 3)); + case_b.push_back(Edge(3, 4)); + case_b.push_back(Edge(4, 1)); + case_b.push_back(Edge(5, 2)); + case_b.push_back(Edge(6, 5)); + + // detect the cycles + cd->mod_graph(V, &case_b); + cycles = cd->detect_cycles(); + + if (cycles != nullptr) { + cout << "cycles->size(): " << cycles->size() << endl; + for (unsigned i = 0; i < case_b.size(); i++) { + // print out the cycles + if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_b[i].first << ", " << case_b[i].second << ")" << endl; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); + rs.push_back(new Rectangle(30,30+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,90,90+5)); + rs.push_back(new Rectangle(65,65+5,90,90+5)); + + assert(rs.size() == V); + + output_svg(rs, case_b, "cycle_detector_case_b.svg", false, true, cycles); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + delete cycles; + } + + // create case C + // case C is a more complicated graph with nested cycles + cout << endl << "ENTERING CASE C" << endl; + V = 14; + case_c.push_back(Edge(0, 1)); + case_c.push_back(Edge(0, 5)); + case_c.push_back(Edge(0, 6)); + case_c.push_back(Edge(2, 0)); + case_c.push_back(Edge(3, 5)); + case_c.push_back(Edge(4, 3)); + case_c.push_back(Edge(5, 4)); + case_c.push_back(Edge(5, 13)); + case_c.push_back(Edge(6, 2)); + case_c.push_back(Edge(6, 9)); + case_c.push_back(Edge(7, 6)); + case_c.push_back(Edge(8, 7)); + case_c.push_back(Edge(9, 10)); + case_c.push_back(Edge(9, 11)); + case_c.push_back(Edge(9, 12)); + case_c.push_back(Edge(10, 6)); + case_c.push_back(Edge(12, 10)); + case_c.push_back(Edge(13, 4)); + + // detect the cycles + //cd = new CycleDetector(V, &case_c); + cd->mod_graph(V, &case_c); + cycles = cd->detect_cycles(); + if (cycles != nullptr) { + cout << "cycles->size(): " << cycles->size() << endl; + for (unsigned i = 0; i < case_c.size(); i++) { + // print out the cycles + if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_c[i].first << ", " << case_c[i].second << ")" << endl; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0 + rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1 + rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2 + rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3 + rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4 + rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5 + rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6 + rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7 + rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8 + rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9 + rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10 + rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11 + rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12 + rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13 + + assert(rs.size() == V); + + output_svg(rs, case_c, "cycle_detector_case_c.svg", false, true, cycles); + for(int i = 0; i < V; i++) { delete rs[i]; } + rs.clear(); + delete cycles; + } + + // create case D + // case D consists of the same graph as case A but with a different starting location + cout << endl << "ENTERING CASE D" << endl; + V = 5; + case_d.push_back(Edge(0, 1)); + case_d.push_back(Edge(1, 2)); + case_d.push_back(Edge(2, 3)); + case_d.push_back(Edge(3, 0)); + case_d.push_back(Edge(4, 1)); + + // detect the cycles + cd->mod_graph(V, &case_d); + cycles = cd->detect_cycles(); + + if (cycles != nullptr) { + cout << "cycles->size(): " << cycles->size() << endl; + for (unsigned i = 0; i < case_d.size(); i++) { + // print out the cycles + if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_d[i].first << ", " << case_d[i].second << ")" << endl; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(65,65+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,60,60+5)); + rs.push_back(new Rectangle(10,10+5,10,10+5)); + + assert(rs.size() == V); + + output_svg(rs, case_d, "cycle_detector_case_d.svg", false, true, cycles); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + delete cycles; + } + else { + cout << "No cycles found" << endl; + } + + // create case E + // case E is a reordering of case C + cout << endl << "ENTERING CASE E" << endl; + V = 14; + case_e.push_back(Edge(0, 6)); + case_e.push_back(Edge(0, 9)); + case_e.push_back(Edge(1, 4)); + case_e.push_back(Edge(3, 10)); + case_e.push_back(Edge(4, 3)); + case_e.push_back(Edge(5, 0)); + case_e.push_back(Edge(6, 7)); + case_e.push_back(Edge(7, 0)); + case_e.push_back(Edge(7, 2)); + case_e.push_back(Edge(7, 10)); + case_e.push_back(Edge(8, 5)); + case_e.push_back(Edge(9, 12)); + case_e.push_back(Edge(9, 11)); + case_e.push_back(Edge(9, 13)); + case_e.push_back(Edge(10, 1)); + case_e.push_back(Edge(10, 4)); + case_e.push_back(Edge(12, 0)); + case_e.push_back(Edge(11, 12)); + + // detect the cycles + cd->mod_graph(V, &case_e); + cycles = cd->detect_cycles(); + if (cycles != nullptr) { + cout << "cycles->size(): " << cycles->size() << endl; + for (unsigned i = 0; i < case_e.size(); i++) { + // print out the cycles + if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_e[i].first << ", " << case_e[i].second << ")" << endl; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6 + rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13 + rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1 + rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3 + rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4 + rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7 + rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2 + rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0 + rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8 + rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9 + rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5 + rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12 + rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10 + rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11 + + assert(rs.size() == V); + + output_svg(rs, case_e, "cycle_detector_case_e.svg", false, true, cycles); + for(int i = 0; i < V; i++) { delete rs[i]; } + rs.clear(); + delete cycles; + } + + // create case F + // case F consists of the same graph with sinks + cout << endl << "ENTERING CASE F" << endl; + V = 3; + case_f.push_back(Edge(0, 1)); + case_f.push_back(Edge(0, 2)); + case_f.push_back(Edge(1, 2)); + + // detect the cycles + cd->mod_graph(V, &case_f); + cycles = cd->detect_cycles(); + + if (cycles != nullptr) { + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); + rs.push_back(new Rectangle(40,40+5,30,30+5)); + rs.push_back(new Rectangle(15,15+5,60,60+5)); + + assert(rs.size() == V); + + output_svg(rs, case_f, "cycle_detector_case_f.svg", false, true, cycles); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + + cout << "No cycles found" << endl; + } + + // This tests the cycle detectors ability to cycle through a chain of cyclic ancestors + cout << endl << "ENTERING CYCLIC ANCESTOR TEST" << endl; + Node a(1), b(2), c(3), d(4), e(5), f(6); + // set up the chain + f.cyclicAncestor = &e; + e.cyclicAncestor = &d; + d.cyclicAncestor = &c; + c.cyclicAncestor = &b; + b.cyclicAncestor = &a; + a.cyclicAncestor = &a; + + Node *ca = cd->get_highest_ca(&f); + if (ca != nullptr) { cout << "Highest cyclic ancestor found at vertex(" << ca->id << ")" << endl; } + + // create case G + // case G hows the ability to find nested cycles and to reassign cyclic ancestors + cout << endl << "ENTERING CASE G" << endl; + V = 7; + case_g.push_back(Edge(0, 1)); + case_g.push_back(Edge(1, 2)); + case_g.push_back(Edge(2, 3)); + case_g.push_back(Edge(3, 4)); + case_g.push_back(Edge(4, 5)); + case_g.push_back(Edge(5, 6)); + case_g.push_back(Edge(6, 5)); + case_g.push_back(Edge(5, 4)); + case_g.push_back(Edge(4, 3)); + case_g.push_back(Edge(3, 2)); + case_g.push_back(Edge(2, 1)); + case_g.push_back(Edge(1, 0)); + case_g.push_back(Edge(0, 6)); + + // detect the cycles + cd->mod_graph(V, &case_g); + cycles = cd->detect_cycles(); + + if (cycles != nullptr) { + cout << "cycles->size(): " << cycles->size() << endl; + for (unsigned i = 0; i < case_g.size(); i++) { + // print out the cycles + if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_g[i].first << ", " << case_g[i].second << ")" << endl; + } + + cout << endl; + + // output a picture + cout << "No picture generated" << endl; + + /*rs.push_back(new Rectangle(50,50+5,10,10+5)); + rs.push_back(new Rectangle(50,50+5,30,30+5)); + rs.push_back(new Rectangle(50,50+5,60,60+5)); + rs.push_back(new Rectangle(10,10+5,70,70+5)); + rs.push_back(new Rectangle(50,50+5,100,100+5)); + rs.push_back(new Rectangle(10,10+5,40,40+5)); + + assert(rs.size() == V); + + output_svg(rs, case_a, "cycle_detector_case_g.svg", false, true, cycles); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear();*/ + delete cycles; + } + else { + cout << "No cycles found" << endl; + } + + // END TEST + delete cd; + + return 0; +} diff --git a/src/3rdparty/adaptagrams/libcola/tests/data/1138_bus.txt b/src/3rdparty/adaptagrams/libcola/tests/data/1138_bus.txt new file mode 100644 index 0000000..fb63ec3 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/data/1138_bus.txt @@ -0,0 +1,1458 @@ +4 0 +562 0 +9 1 +562 1 +10 2 +33 2 +34 2 +103 2 +474 2 +6 3 +26 3 +100 3 +101 3 +102 3 +8 4 +6 5 +36 5 +97 5 +102 5 +36 6 +100 6 +101 6 +102 6 +25 7 +34 7 +723 7 +9 8 +103 8 +103 9 +11 10 +37 10 +565 10 +33 12 +103 12 +412 13 +15 14 +16 14 +17 14 +18 14 +410 14 +20 19 +36 19 +101 19 +21 20 +22 20 +23 20 +24 20 +34 25 +27 26 +28 26 +29 26 +100 26 +31 30 +99 30 +99 31 +99 32 +103 33 +552 33 +103 34 +709 34 +710 35 +101 36 +38 37 +97 37 +411 37 +98 38 +40 39 +42 39 +44 39 +41 40 +43 40 +145 42 +485 43 +48 44 +47 45 +47 46 +53 47 +505 47 +49 48 +52 48 +50 49 +51 49 +124 51 +53 52 +54 52 +424 53 +444 53 +446 53 +62 55 +65 56 +69 57 +66 58 +67 59 +129 60 +128 61 +63 62 +64 62 +70 63 +130 63 +225 63 +1094 64 +66 65 +67 65 +73 65 +182 65 +225 65 +67 66 +68 66 +73 67 +89 67 +200 67 +69 68 +181 69 +195 69 +1062 69 +1064 69 +1073 69 +71 70 +72 71 +120 71 +74 73 +75 73 +77 73 +79 73 +118 73 +203 74 +809 74 +917 74 +76 75 +77 75 +126 75 +1049 76 +78 77 +451 77 +415 78 +416 78 +453 78 +80 79 +446 79 +451 79 +447 80 +449 80 +463 80 +93 81 +93 82 +94 83 +86 84 +125 84 +86 85 +240 85 +250 85 +252 85 +266 85 +268 85 +282 85 +290 85 +292 85 +293 85 +301 85 +314 85 +87 86 +104 88 +114 88 +90 89 +91 90 +107 90 +114 90 +115 90 +92 91 +93 92 +251 92 +263 92 +270 92 +287 92 +291 92 +292 92 +293 92 +321 92 +322 92 +323 92 +324 92 +325 92 +95 93 +263 93 +317 93 +324 93 +96 94 +261 94 +267 94 +299 94 +144 95 +703 95 +704 95 +267 96 +412 98 +724 99 +731 99 +101 100 +102 100 +102 101 +477 102 +105 104 +108 104 +107 106 +109 107 +1028 108 +110 109 +327 109 +366 109 +369 109 +366 110 +367 110 +700 110 +112 111 +369 111 +685 111 +113 112 +114 112 +689 112 +1008 113 +116 115 +125 115 +118 117 +122 118 +120 119 +121 120 +503 120 +122 121 +123 121 +124 122 +124 123 +126 123 +125 124 +128 124 +545 124 +128 125 +127 126 +132 129 +172 129 +212 129 +131 130 +132 130 +135 130 +143 131 +741 131 +133 132 +135 134 +138 134 +739 134 +140 135 +138 136 +140 136 +760 136 +140 137 +876 137 +881 137 +139 138 +828 139 +829 139 +257 141 +365 141 +143 142 +742 142 +744 142 +825 142 +826 143 +317 144 +702 144 +146 145 +147 146 +165 148 +172 149 +174 150 +179 151 +182 152 +206 153 +197 154 +212 155 +218 156 +225 157 +181 158 +204 158 +171 159 +232 159 +221 160 +742 160 +162 161 +168 161 +208 161 +222 161 +231 161 +185 162 +200 162 +226 162 +165 163 +165 164 +166 164 +174 164 +193 164 +191 165 +200 165 +217 165 +174 166 +179 167 +208 167 +186 168 +187 169 +193 169 +177 170 +216 170 +172 171 +221 171 +754 171 +183 172 +210 173 +215 173 +178 174 +176 175 +177 175 +206 175 +206 176 +213 177 +216 177 +202 178 +208 179 +182 180 +182 181 +204 181 +220 181 +183 182 +200 182 +225 182 +192 183 +212 183 +186 184 +186 185 +217 185 +187 186 +205 186 +208 186 +210 188 +215 188 +198 189 +194 190 +196 190 +197 190 +210 190 +198 191 +217 191 +219 191 +197 192 +198 192 +207 192 +215 193 +210 194 +211 196 +200 199 +201 199 +217 200 +202 201 +220 204 +215 205 +207 206 +223 206 +214 209 +216 209 +217 209 +211 210 +503 212 +216 213 +217 215 +219 218 +229 218 +221 220 +224 220 +224 221 +232 221 +742 221 +231 222 +1025 223 +227 226 +228 227 +230 227 +231 227 +231 230 +235 233 +306 233 +235 234 +242 234 +269 234 +271 234 +297 234 +298 234 +285 235 +260 236 +286 236 +308 236 +365 236 +701 236 +238 237 +269 237 +269 238 +280 238 +258 239 +241 240 +245 240 +252 240 +256 240 +265 240 +274 240 +278 240 +288 240 +290 240 +291 240 +292 240 +293 240 +298 240 +309 240 +320 240 +326 240 +243 241 +244 241 +271 243 +297 244 +309 245 +247 246 +254 246 +254 247 +281 248 +256 249 +262 249 +288 249 +316 249 +266 250 +309 251 +312 251 +254 253 +284 253 +257 254 +259 254 +262 254 +289 255 +316 255 +320 255 +260 257 +326 257 +277 258 +288 259 +267 261 +275 261 +313 261 +310 263 +275 264 +299 264 +306 265 +281 266 +283 266 +301 266 +269 267 +300 267 +283 268 +274 269 +278 269 +279 269 +317 269 +319 269 +273 272 +302 272 +314 272 +311 273 +284 276 +288 276 +308 277 +291 282 +290 287 +297 294 +296 295 +298 296 +695 299 +313 300 +311 302 +304 303 +314 303 +328 303 +314 304 +321 305 +322 307 +325 310 +314 311 +315 314 +318 314 +322 314 +321 315 +703 317 +328 318 +324 323 +334 329 +335 330 +336 331 +349 332 +349 333 +336 334 +336 335 +337 336 +338 336 +339 336 +339 337 +339 338 +340 339 +341 339 +341 340 +342 341 +343 341 +344 341 +369 341 +345 342 +345 343 +345 344 +346 345 +348 345 +366 345 +347 346 +348 347 +349 348 +365 350 +352 351 +407 351 +408 351 +362 352 +381 352 +381 353 +382 353 +374 354 +382 355 +397 355 +393 356 +394 356 +478 357 +473 358 +714 359 +478 360 +479 360 +402 361 +713 361 +363 362 +364 362 +372 362 +373 362 +387 362 +394 362 +406 362 +473 362 +698 365 +367 366 +371 366 +370 368 +371 370 +375 374 +376 374 +377 374 +378 374 +379 374 +380 374 +388 374 +403 374 +383 382 +384 382 +385 382 +386 382 +391 382 +388 387 +389 387 +390 387 +394 387 +400 387 +404 387 +394 391 +473 392 +478 392 +394 393 +397 394 +398 394 +404 394 +405 394 +406 394 +473 394 +405 395 +715 395 +716 395 +715 396 +716 396 +472 399 +401 400 +713 400 +408 403 +478 405 +482 405 +715 405 +716 405 +410 409 +411 409 +730 409 +475 410 +476 410 +485 410 +412 411 +477 411 +708 411 +723 411 +430 413 +432 413 +431 414 +432 414 +432 415 +461 415 +432 416 +461 416 +418 417 +544 417 +420 419 +421 419 +469 419 +424 422 +515 422 +465 423 +515 423 +425 424 +426 424 +465 424 +436 425 +518 425 +428 427 +429 427 +430 427 +431 427 +433 432 +509 432 +563 432 +509 434 +533 435 +437 436 +438 436 +440 436 +457 436 +439 438 +459 438 +441 440 +443 442 +469 442 +505 442 +515 442 +457 443 +445 444 +446 444 +448 446 +536 446 +463 447 +449 448 +450 449 +452 451 +454 453 +456 455 +563 455 +458 457 +459 457 +460 459 +462 461 +464 463 +544 463 +967 464 +466 465 +543 467 +542 468 +471 470 +477 470 +480 470 +491 470 +706 470 +707 470 +473 472 +709 474 +723 474 +481 475 +477 476 +707 477 +708 477 +479 478 +713 478 +725 478 +483 480 +484 480 +490 480 +491 480 +732 480 +482 481 +708 483 +732 483 +490 484 +730 485 +490 486 +490 487 +491 488 +491 489 +491 490 +733 490 +706 491 +706 492 +504 493 +512 494 +520 495 +521 496 +522 497 +499 498 +818 498 +913 498 +501 500 +504 500 +506 500 +520 500 +530 500 +535 500 +606 501 +608 501 +612 501 +936 501 +506 502 +512 502 +552 502 +504 503 +520 504 +525 504 +577 504 +507 506 +508 506 +514 506 +520 506 +521 506 +546 506 +618 507 +638 507 +780 507 +510 508 +514 508 +519 508 +533 508 +519 509 +913 510 +925 510 +519 511 +513 512 +539 512 +789 513 +794 513 +515 514 +516 514 +517 514 +535 514 +546 514 +992 516 +994 516 +956 518 +966 518 +521 520 +522 521 +581 522 +769 522 +778 522 +801 522 +532 523 +984 523 +1000 523 +567 524 +526 525 +530 525 +920 526 +932 526 +1067 526 +1072 526 +1073 526 +1123 526 +528 527 +808 527 +818 527 +577 529 +582 529 +779 529 +796 529 +802 529 +531 530 +533 530 +553 531 +646 531 +651 531 +662 531 +667 531 +671 531 +672 531 +676 531 +907 531 +911 531 +917 531 +1046 531 +534 533 +535 533 +541 533 +884 534 +536 535 +537 535 +538 535 +541 535 +808 537 +913 537 +947 537 +952 537 +963 537 +799 539 +542 540 +542 541 +544 541 +545 541 +543 542 +550 547 +562 548 +565 549 +551 550 +554 550 +565 550 +557 551 +559 551 +560 552 +709 552 +573 553 +908 553 +555 554 +556 554 +563 554 +565 554 +558 555 +578 555 +620 555 +902 555 +557 556 +978 557 +979 557 +985 557 +988 557 +990 557 +997 557 +999 557 +578 558 +979 559 +561 560 +565 560 +562 561 +566 562 +566 564 +566 565 +772 567 +794 567 +784 568 +578 569 +775 570 +782 571 +795 572 +580 574 +581 575 +783 575 +785 576 +801 576 +1089 576 +779 577 +579 578 +781 578 +782 578 +894 578 +926 578 +586 579 +775 580 +795 580 +796 580 +798 580 +779 582 +802 582 +584 583 +1067 583 +606 584 +612 584 +658 584 +596 585 +597 586 +613 586 +594 587 +596 587 +590 588 +594 589 +615 589 +600 590 +610 591 +603 592 +599 593 +596 595 +602 595 +606 595 +1104 598 +600 599 +781 599 +601 600 +632 600 +639 601 +603 602 +604 602 +1091 602 +611 603 +614 603 +606 604 +609 605 +609 607 +1100 607 +1067 608 +614 610 +1122 616 +628 617 +638 617 +619 618 +631 619 +623 620 +1060 620 +624 621 +640 621 +638 622 +641 622 +637 623 +634 624 +633 625 +634 625 +638 626 +630 627 +641 627 +636 628 +642 628 +630 629 +634 629 +795 629 +633 631 +640 631 +635 634 +1093 635 +651 643 +661 643 +649 644 +1059 644 +663 645 +1050 645 +1040 646 +677 647 +1041 647 +671 648 +1054 648 +652 649 +669 650 +1044 650 +652 651 +662 651 +665 651 +667 651 +675 651 +1053 651 +1047 652 +676 653 +1056 653 +656 654 +664 654 +677 655 +1054 656 +670 657 +671 657 +676 658 +1049 659 +1057 659 +676 660 +671 661 +1055 663 +681 664 +680 665 +1050 666 +678 668 +1057 668 +1120 669 +678 670 +672 671 +681 671 +1048 671 +1049 671 +1051 671 +1057 671 +1120 671 +674 673 +1045 673 +1049 674 +1042 675 +677 676 +1040 676 +1058 676 +1046 679 +1056 679 +1052 680 +688 682 +688 683 +690 684 +686 685 +687 685 +688 687 +693 687 +698 687 +699 687 +701 687 +692 688 +690 689 +693 689 +696 689 +691 690 +694 690 +694 692 +694 693 +697 696 +699 698 +706 705 +725 706 +708 707 +723 710 +733 710 +713 711 +713 712 +714 713 +733 713 +716 715 +723 717 +723 718 +723 719 +723 720 +723 721 +723 722 +724 723 +733 723 +727 726 +730 726 +730 727 +729 728 +730 728 +730 729 +742 734 +741 735 +742 736 +741 737 +743 738 +740 739 +741 739 +743 739 +748 740 +758 740 +742 741 +745 742 +755 743 +745 744 +747 746 +757 746 +756 747 +752 748 +750 749 +758 749 +756 751 +761 751 +756 753 +764 753 +763 754 +756 755 +760 759 +765 760 +766 760 +762 761 +767 765 +768 767 +771 767 +822 769 +771 770 +773 772 +794 772 +800 772 +801 772 +775 774 +780 774 +780 775 +795 775 +796 775 +1126 775 +792 776 +794 776 +799 776 +778 777 +779 778 +786 778 +796 779 +948 779 +782 781 +801 783 +785 784 +787 784 +795 784 +796 784 +801 784 +1127 785 +948 786 +788 787 +795 787 +1131 787 +1093 788 +790 789 +794 789 +798 791 +1109 791 +793 792 +824 792 +794 793 +799 793 +798 795 +797 796 +802 796 +804 796 +1118 796 +1113 797 +1136 801 +803 802 +1137 804 +820 805 +886 806 +896 807 +919 808 +810 809 +917 809 +908 811 +884 812 +939 812 +1121 812 +814 813 +908 813 +917 813 +816 815 +926 815 +817 816 +906 816 +819 818 +887 820 +896 820 +920 820 +879 821 +884 821 +934 821 +824 823 +836 827 +837 827 +873 827 +832 828 +838 828 +832 829 +839 829 +840 830 +868 830 +841 831 +868 831 +842 832 +843 833 +873 833 +844 834 +861 834 +845 835 +868 835 +858 837 +859 837 +847 846 +872 847 +853 848 +862 848 +863 848 +854 849 +872 849 +855 850 +857 850 +856 851 +868 851 +875 852 +872 857 +860 859 +862 861 +868 862 +864 863 +868 863 +868 865 +876 865 +877 866 +868 867 +870 867 +876 867 +869 868 +870 869 +876 869 +881 871 +881 872 +877 873 +875 874 +881 874 +877 876 +882 876 +881 878 +881 880 +936 883 +1122 883 +913 884 +917 884 +894 885 +926 885 +936 885 +895 886 +896 886 +923 887 +916 888 +890 889 +907 889 +916 889 +892 891 +898 891 +926 891 +920 893 +935 893 +1125 893 +1124 894 +896 895 +912 896 +916 896 +943 896 +913 897 +925 897 +899 898 +907 898 +912 900 +1128 900 +905 901 +986 902 +904 903 +938 903 +943 903 +921 905 +938 905 +922 906 +911 907 +916 907 +926 907 +909 908 +911 910 +934 913 +937 913 +962 913 +925 914 +990 915 +917 916 +929 916 +918 917 +1129 917 +939 918 +922 920 +923 920 +926 920 +932 920 +936 920 +929 921 +1132 921 +924 923 +927 926 +936 926 +928 927 +936 927 +930 929 +948 931 +933 932 +941 932 +946 934 +936 935 +1133 935 +953 939 +953 940 +943 942 +960 944 +964 945 +951 947 +954 947 +956 947 +957 947 +963 947 +950 949 +954 949 +955 949 +964 950 +968 950 +974 950 +959 951 +954 952 +958 953 +957 956 +966 956 +972 956 +972 959 +961 960 +962 960 +967 960 +965 961 +971 962 +967 964 +968 964 +970 965 +969 968 +971 970 +982 973 +976 975 +988 975 +1000 975 +988 977 +982 978 +981 980 +983 980 +997 980 +985 982 +986 984 +988 984 +998 986 +992 987 +994 987 +989 988 +991 990 +993 992 +996 994 +997 994 +996 995 +997 996 +1026 1001 +1034 1002 +1031 1003 +1038 1004 +1006 1005 +1012 1005 +1018 1005 +1020 1005 +1029 1005 +1034 1005 +1022 1007 +1009 1008 +1017 1008 +1018 1008 +1020 1008 +1021 1008 +1039 1008 +1039 1010 +1039 1011 +1022 1012 +1028 1012 +1029 1012 +1036 1012 +1037 1012 +1038 1012 +1038 1013 +1028 1014 +1023 1015 +1033 1015 +1028 1016 +1032 1018 +1020 1019 +1023 1022 +1024 1022 +1026 1022 +1033 1023 +1027 1024 +1026 1025 +1027 1026 +1034 1026 +1030 1029 +1033 1031 +1035 1031 +1035 1034 +1049 1042 +1049 1043 +1052 1043 +1046 1044 +1057 1045 +1053 1048 +1050 1049 +1051 1049 +1055 1050 +1055 1054 +1057 1054 +1060 1058 +1071 1061 +1084 1061 +1073 1062 +1074 1063 +1086 1063 +1076 1064 +1079 1064 +1067 1065 +1070 1066 +1068 1067 +1091 1067 +1085 1068 +1076 1069 +1112 1069 +1087 1070 +1074 1071 +1073 1072 +1074 1073 +1080 1073 +1085 1073 +1081 1074 +1076 1075 +1077 1076 +1079 1076 +1087 1076 +1094 1076 +1083 1077 +1084 1077 +1116 1078 +1086 1082 +1105 1088 +1111 1088 +1090 1089 +1092 1090 +1107 1090 +1097 1092 +1095 1094 +1099 1094 +1104 1094 +1112 1094 +1102 1095 +1106 1095 +1111 1095 +1099 1096 +1098 1097 +1100 1099 +1119 1100 +1111 1101 +1117 1103 +1118 1103 +1108 1105 +1113 1109 +1118 1110 +1114 1113 +1115 1113 +1119 1116 +1135 1121 +1134 1123 +1134 1128 +1135 1130 diff --git a/src/3rdparty/adaptagrams/libcola/tests/data/uetzNetworkGSC-all.gml b/src/3rdparty/adaptagrams/libcola/tests/data/uetzNetworkGSC-all.gml new file mode 100644 index 0000000..99c4053 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/data/uetzNetworkGSC-all.gml @@ -0,0 +1,26139 @@ +graph [ + directed 1 + node [ + id 1 + pajek_id 1 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1294.0522048684777 + y 1122.6497967871214 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 2 + pajek_id 2 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2055.718178872795 + y 1059.2791761907554 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 3 + pajek_id 3 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1256.6354129633914 + y 1695.6123461841953 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 4 + pajek_id 4 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1184.7211808078375 + y 935.8910996786233 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 5 + pajek_id 5 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2298.0954772536134 + y 1437.502173559352 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 6 + pajek_id 6 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1897.6814785435922 + y 550.7159507323732 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 7 + pajek_id 7 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1901.322129497895 + y 1044.3438487090452 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 8 + pajek_id 8 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2780.868057459027 + y 880.0661109912785 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 9 + pajek_id 9 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1538.3317441868267 + y 1411.5744527134639 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 10 + pajek_id 10 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 396.0152636117873 + y 1131.0468905861571 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 11 + pajek_id 11 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2807.6418756553476 + y 1965.421804479885 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 12 + pajek_id 12 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1483.7207919217562 + y 1613.0999970511837 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 13 + pajek_id 13 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 254.92863023355244 + y 592.4142543364859 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 14 + pajek_id 14 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2356.3555481078492 + y 762.7982298395269 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 15 + pajek_id 15 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 358.86149369612554 + y 718.6522617063977 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 16 + pajek_id 16 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1989.7728584457432 + y 593.5406100260483 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 17 + pajek_id 17 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1176.0589697518428 + y 274.6599182522517 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 18 + pajek_id 18 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 815.4286293876028 + y 1519.2372285089286 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 19 + pajek_id 19 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1292.8058349907271 + y 1534.9166231756176 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 20 + pajek_id 20 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1712.1139015143726 + y 1743.9840389531971 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 21 + pajek_id 21 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1159.0926195442978 + y 60.0 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 22 + pajek_id 22 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1698.8281996861965 + y 938.1788913033595 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 23 + pajek_id 23 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2117.1960623698105 + y 377.3080137329175 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 24 + pajek_id 24 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1988.5172976949088 + y 1626.9118171301184 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 25 + pajek_id 25 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1951.0677192239534 + y 1227.8213042650113 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 26 + pajek_id 26 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1209.2907663600151 + y 571.9488583740487 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 27 + pajek_id 27 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1553.217522639471 + y 514.0779699887444 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 28 + pajek_id 28 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1216.2131040787344 + y 1306.3244872331861 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 29 + pajek_id 29 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2495.910234238144 + y 1509.2542926345884 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 30 + pajek_id 30 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2589.368846133916 + y 902.4410855851487 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 31 + pajek_id 31 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1900.4466132863522 + y 960.4878587369396 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 32 + pajek_id 32 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1480.404193494587 + y 503.45364906241434 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 33 + pajek_id 33 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1786.4697371577445 + y 2321.7848119927116 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 34 + pajek_id 34 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1609.213005284541 + y 1590.2108893694465 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 35 + pajek_id 35 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 600.5008950141041 + y 1277.5609673161835 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 36 + pajek_id 36 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 60.0 + y 768.8625017780407 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 37 + pajek_id 37 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 382.9141452731493 + y 1259.7726277058914 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 38 + pajek_id 38 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 687.2063369120657 + y 1082.3933671094655 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 39 + pajek_id 39 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1027.5033292569951 + y 1088.9830040963775 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 40 + pajek_id 40 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1632.4747876484166 + y 710.5037615118014 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 41 + pajek_id 41 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 748.4550588733631 + y 1062.8651339361004 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 42 + pajek_id 42 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 963.8979533416527 + y 1723.250139029375 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 43 + pajek_id 43 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1411.3947986828978 + y 1157.8550891438708 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 44 + pajek_id 44 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2648.6214914664592 + y 360.6532255567197 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 45 + pajek_id 45 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1012.524198351514 + y 1566.9080651878785 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 46 + pajek_id 46 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1673.0588337518445 + y 1520.3103374282064 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 47 + pajek_id 47 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2292.062233641057 + y 807.7075902196876 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 48 + pajek_id 48 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2077.483685032171 + y 1214.6266410102694 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 49 + pajek_id 49 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1250.7982377330313 + y 984.2480480318932 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 50 + pajek_id 50 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 826.5624689443126 + y 1458.2342219655006 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 51 + pajek_id 51 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1043.503156998524 + y 1914.4120411204835 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 52 + pajek_id 52 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1097.4841298080655 + y 608.9543419822743 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 53 + pajek_id 53 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1151.8669553096083 + y 1688.783506135614 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 54 + pajek_id 54 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1100.1774339936296 + y 449.9360013393336 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 55 + pajek_id 55 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1797.1270429940496 + y 517.7947984237063 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 56 + pajek_id 56 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1958.7774891972645 + y 951.067065374911 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 57 + pajek_id 57 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1320.7173946510097 + y 666.953428346941 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 58 + pajek_id 58 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 409.511718757674 + y 754.8270051102944 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 59 + pajek_id 59 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 456.52944375010406 + y 1644.5489937771122 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 60 + pajek_id 60 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1650.4029796871373 + y 1281.9794653489726 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 61 + pajek_id 61 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2203.5059215970086 + y 1103.986465771347 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 62 + pajek_id 62 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1648.5790338469196 + y 1619.5713910478498 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 63 + pajek_id 63 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1441.449939123268 + y 278.4421140050705 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 64 + pajek_id 64 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1646.3755592037082 + y 1867.8552090742746 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 65 + pajek_id 65 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1690.4064173252282 + y 1106.6596200585911 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 66 + pajek_id 66 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1375.2079396723311 + y 1567.1239230162141 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 67 + pajek_id 67 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1381.6936762897983 + y 930.9429010096588 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 68 + pajek_id 68 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2246.515691754706 + y 1228.672822112808 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 69 + pajek_id 69 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2513.1221976499774 + y 2123.5607442911432 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 70 + pajek_id 70 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 325.1248018822786 + y 1301.1300387216584 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 71 + pajek_id 71 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 905.4567507395766 + y 1635.3403866013616 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 72 + pajek_id 72 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1409.3758774490468 + y 2445.8494772528247 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 73 + pajek_id 73 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 270.55209645867626 + y 1976.484880612065 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 74 + pajek_id 74 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1846.104723102188 + y 2357.13888536703 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 75 + pajek_id 75 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1931.8467589445268 + y 1416.3573716456167 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 76 + pajek_id 76 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 219.41564456563447 + y 351.74606877700694 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 77 + pajek_id 77 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1574.267945560331 + y 994.005057804803 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 78 + pajek_id 78 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2258.765897434142 + y 975.7865089151361 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 79 + pajek_id 79 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1003.0168039671166 + y 818.3149905376152 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 80 + pajek_id 80 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2162.351384651877 + y 639.3742942428671 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 81 + pajek_id 81 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1175.3498984884113 + y 205.4073989675603 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 82 + pajek_id 82 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1025.8732247508035 + y 146.60499318409438 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 83 + pajek_id 83 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 784.8316721743003 + y 739.8886774008013 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 84 + pajek_id 84 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2358.3905436512314 + y 1757.8833117002607 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 85 + pajek_id 85 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 187.0231231288874 + y 464.9030131392583 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 86 + pajek_id 86 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1680.1684155817545 + y 989.3992861143759 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 87 + pajek_id 87 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1592.5433115122046 + y 1133.073079548351 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 88 + pajek_id 88 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 984.0210982272379 + y 1907.6496174273066 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 89 + pajek_id 89 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1908.2544551347682 + y 1953.0395792102486 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 90 + pajek_id 90 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1760.6396933740039 + y 454.1561397683437 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 91 + pajek_id 91 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1510.4214829476575 + y 255.4247158499462 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 92 + pajek_id 92 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2156.911158437812 + y 1737.2936541047445 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 93 + pajek_id 93 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2330.4433111549088 + y 1066.919264412134 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 94 + pajek_id 94 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1489.0049739638976 + y 1102.8420420131365 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 95 + pajek_id 95 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1381.821327085725 + y 1425.799958792195 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 96 + pajek_id 96 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2026.5031721150344 + y 1195.03677714938 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 97 + pajek_id 97 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1566.5985533781122 + y 2134.591986800821 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 98 + pajek_id 98 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1866.8579043433465 + y 496.54994132044186 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 99 + pajek_id 99 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1709.8596572466934 + y 1537.0985557194695 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 100 + pajek_id 100 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1058.888749291412 + y 1423.3219452240978 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 101 + pajek_id 101 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1026.841049144297 + y 1526.2197338662158 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 102 + pajek_id 102 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1234.128325564796 + y 1058.423971642138 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 103 + pajek_id 103 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2269.604004829725 + y 1961.2578434564753 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 104 + pajek_id 104 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1204.604308471341 + y 331.2782608195139 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 105 + pajek_id 105 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1456.5954783621391 + y 2393.969680005851 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 106 + pajek_id 106 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1030.6221217055054 + y 1655.7105879228054 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 107 + pajek_id 107 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1825.2038903621162 + y 1764.5225692398108 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 108 + pajek_id 108 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 855.344393246044 + y 1581.4397578617163 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 109 + pajek_id 109 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2290.109859607357 + y 1866.4142704202714 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 110 + pajek_id 110 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2016.9300946422195 + y 1800.0828289087844 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 111 + pajek_id 111 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2311.298477488912 + y 1203.9224047333146 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 112 + pajek_id 112 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2173.9918013172064 + y 1358.97529576786 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 113 + pajek_id 113 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 402.8249532029572 + y 2005.0535234158124 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 114 + pajek_id 114 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1370.447752295795 + y 1698.544524957459 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 115 + pajek_id 115 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 824.5410187470699 + y 2203.3482170965663 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 116 + pajek_id 116 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1899.5312814624624 + y 341.64788217907767 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 117 + pajek_id 117 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1275.5334231652173 + y 435.5539332588777 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 118 + pajek_id 118 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1799.057369842763 + y 898.644722551811 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 119 + pajek_id 119 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 936.3882990544396 + y 542.1677084693897 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 120 + pajek_id 120 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2035.2157086365958 + y 549.5503878259726 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 121 + pajek_id 121 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2306.5008116638155 + y 2172.8922465255055 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 122 + pajek_id 122 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 794.0600584680333 + y 1767.0092661358444 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 123 + pajek_id 123 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 967.8528471899847 + y 1305.606206649742 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 124 + pajek_id 124 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2478.6497152538377 + y 1203.6776389496872 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 125 + pajek_id 125 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1997.321116636319 + y 2192.367195588601 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 126 + pajek_id 126 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1177.3434085029842 + y 778.6424846605535 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 127 + pajek_id 127 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1585.5048018331465 + y 1455.2573996761384 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 128 + pajek_id 128 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 472.28484900676176 + y 718.0672675218485 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 129 + pajek_id 129 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 794.0849295823707 + y 1371.6459663216558 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 130 + pajek_id 130 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2008.8851806591924 + y 1293.0028606195688 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 131 + pajek_id 131 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1441.295381525302 + y 564.6073812973832 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 132 + pajek_id 132 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1861.1042483735764 + y 1523.2486386191717 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 133 + pajek_id 133 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 957.7655245033009 + y 114.39870152004505 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 134 + pajek_id 134 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1961.9942877269461 + y 124.43728726767961 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 135 + pajek_id 135 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2317.512327717449 + y 924.258173136443 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 136 + pajek_id 136 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1800.1506277595804 + y 2261.975902475042 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 137 + pajek_id 137 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 595.234814691012 + y 1025.317899636531 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 138 + pajek_id 138 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 964.840641154222 + y 247.01750927240698 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 139 + pajek_id 139 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 588.9999815953205 + y 2079.3235704527674 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 140 + pajek_id 140 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2110.3560493557006 + y 505.8109983485984 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 141 + pajek_id 141 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1399.3112848730054 + y 1227.804800096851 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 142 + pajek_id 142 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1334.1378233999883 + y 1813.8827309253875 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 143 + pajek_id 143 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1805.918047276415 + y 624.9341989045439 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 144 + pajek_id 144 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1467.2887831794974 + y 1491.092756875548 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 145 + pajek_id 145 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1369.2679808531936 + y 1127.5618294352796 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 146 + pajek_id 146 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2025.2400562476682 + y 1570.3163109170114 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 147 + pajek_id 147 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2055.8364822532835 + y 684.3901430356791 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 148 + pajek_id 148 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2458.5244327113796 + y 1391.3830145494958 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 149 + pajek_id 149 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1552.825479830451 + y 1252.8654366828728 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 150 + pajek_id 150 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2642.703200490143 + y 873.2840758651536 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 151 + pajek_id 151 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2493.621315614442 + y 1057.6778103427564 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 152 + pajek_id 152 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2048.524265153669 + y 2396.6375817898183 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 153 + pajek_id 153 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1295.8980767195865 + y 1281.8240646387455 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 154 + pajek_id 154 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 948.0256773985192 + y 874.4275219392624 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 155 + pajek_id 155 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1060.558142370161 + y 2121.7015632861817 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 156 + pajek_id 156 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1588.0692311325395 + y 2419.735277431223 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 157 + pajek_id 157 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1399.2208755506806 + y 668.8198477332975 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 158 + pajek_id 158 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1580.2791211407448 + y 894.9665199234698 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 159 + pajek_id 159 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1585.445364428028 + y 1518.9113878761736 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 160 + pajek_id 160 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2149.623427593962 + y 1585.663447804202 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 161 + pajek_id 161 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1073.2288913412556 + y 1374.5854206557112 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 162 + pajek_id 162 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 493.61694579516404 + y 1365.494793302807 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 163 + pajek_id 163 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1286.2369050296045 + y 1067.3473338636227 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 164 + pajek_id 164 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 927.1316689881887 + y 1385.503225606381 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 165 + pajek_id 165 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2193.2522202024475 + y 1206.1206658070653 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 166 + pajek_id 166 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 772.1411120215096 + y 1970.8119423759322 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 167 + pajek_id 167 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1145.792529275603 + y 1177.4939749954644 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 168 + pajek_id 168 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 782.4194952141179 + y 2042.5751921467117 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 169 + pajek_id 169 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1254.116200428233 + y 2594.759114678682 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 170 + pajek_id 170 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2678.2734809510507 + y 2096.8291622390625 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 171 + pajek_id 171 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2400.4372550336543 + y 1652.7179946898918 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 172 + pajek_id 172 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1386.2112759254533 + y 1638.7948048718672 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 173 + pajek_id 173 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 943.8883491218697 + y 1073.7919591358736 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 174 + pajek_id 174 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1179.1603874552718 + y 1122.3817446803446 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 175 + pajek_id 175 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2233.8795632906877 + y 1527.7817714192893 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 176 + pajek_id 176 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2163.4669644146798 + y 1260.955553479491 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 177 + pajek_id 177 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1869.4250586602952 + y 2472.448020780895 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 178 + pajek_id 178 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1112.7457233061032 + y 1329.0846670907608 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 179 + pajek_id 179 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1118.8056866951574 + y 852.6869706221119 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 180 + pajek_id 180 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1307.2508861643091 + y 2462.7701746985686 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 181 + pajek_id 181 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1380.5745060829129 + y 1076.2706855348051 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 182 + pajek_id 182 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2036.4065621255 + y 2529.571297575046 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 183 + pajek_id 183 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1074.9510652351762 + y 801.3658771409633 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 184 + pajek_id 184 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 255.45722686156626 + y 1805.532111761012 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 185 + pajek_id 185 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2342.5052901155595 + y 1982.0954207181567 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 186 + pajek_id 186 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1178.1746215798703 + y 871.8443836872366 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 187 + pajek_id 187 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1537.0518689637947 + y 1540.5124880929002 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 188 + pajek_id 188 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1236.2077456256104 + y 1534.272658840872 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 189 + pajek_id 189 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1621.2397812102838 + y 1400.4425940981625 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 190 + pajek_id 190 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 766.3905805597286 + y 886.402470142523 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 191 + pajek_id 191 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2168.7884396974873 + y 550.016818013951 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 192 + pajek_id 192 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 993.9061877291988 + y 1029.772643432917 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 193 + pajek_id 193 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 463.0359831362713 + y 1022.0861273460611 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 194 + pajek_id 194 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 639.0038131671084 + y 555.7612618656989 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 195 + pajek_id 195 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1814.9683409976778 + y 2445.753076164031 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 196 + pajek_id 196 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1686.4439166148054 + y 1938.4699461276296 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 197 + pajek_id 197 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 930.0951591923147 + y 1241.663890087508 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 198 + pajek_id 198 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 520.2346633262122 + y 1199.2357895089199 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 199 + pajek_id 199 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1971.6382604373562 + y 343.1014653785635 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 200 + pajek_id 200 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2027.0179357401762 + y 1349.107156613678 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 201 + pajek_id 201 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2087.081528540994 + y 802.4499939958602 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 202 + pajek_id 202 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 625.0171226735023 + y 1914.7856839077308 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 203 + pajek_id 203 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1899.9652173985933 + y 2072.1438307043504 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 204 + pajek_id 204 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1606.0783659797662 + y 1837.1508274695605 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 205 + pajek_id 205 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 901.3919870421247 + y 1513.1982896128998 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 206 + pajek_id 206 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2538.1638433893568 + y 1616.7551606942914 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 207 + pajek_id 207 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1866.691494571614 + y 2114.4934954074397 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 208 + pajek_id 208 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1028.2574487173333 + y 973.0790458888064 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 209 + pajek_id 209 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1753.7616445481387 + y 928.4269154425315 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 210 + pajek_id 210 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 434.8320641528154 + y 900.7941512774352 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 211 + pajek_id 211 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1197.692612238198 + y 1656.3283202472192 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 212 + pajek_id 212 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2262.872473159019 + y 855.5192882246674 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 213 + pajek_id 213 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2005.7033668568552 + y 1687.3129033516693 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 214 + pajek_id 214 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2005.4330911080656 + y 1248.6067376996575 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 215 + pajek_id 215 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1497.6387156758587 + y 409.988817350047 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 216 + pajek_id 216 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1511.6499513985573 + y 2019.1033155888222 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 217 + pajek_id 217 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1832.9845660337855 + y 1594.9330492361391 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 218 + pajek_id 218 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2124.163466904739 + y 1121.7594517130105 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 219 + pajek_id 219 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2114.0594425877107 + y 879.072087899176 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 220 + pajek_id 220 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2060.685078868419 + y 1835.1973884802942 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 221 + pajek_id 221 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2250.360824827312 + y 908.8247250753682 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 222 + pajek_id 222 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1619.44524541997 + y 1208.958636465997 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 223 + pajek_id 223 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1420.5578431824722 + y 1022.1078286320392 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 224 + pajek_id 224 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1804.5906551872706 + y 1356.7859367888193 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 225 + pajek_id 225 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1182.3901258139676 + y 1078.275091742608 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 226 + pajek_id 226 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 939.5649257137159 + y 750.6386331311932 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 227 + pajek_id 227 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1227.5697565955718 + y 1194.722525770867 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 228 + pajek_id 228 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1677.315636418083 + y 818.1002681824733 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 229 + pajek_id 229 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1969.8218697907696 + y 2124.400924405766 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 230 + pajek_id 230 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1346.0361911089835 + y 591.0926251849802 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 231 + pajek_id 231 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1937.4480655403545 + y 1484.3086656977262 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 232 + pajek_id 232 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 913.1080893674856 + y 2448.9010701058382 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 233 + pajek_id 233 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 980.1355123328368 + y 2143.0193206720637 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 234 + pajek_id 234 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2468.507735819624 + y 680.6867726745393 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 235 + pajek_id 235 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 961.6345650781091 + y 965.0860824711237 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 236 + pajek_id 236 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 492.09673495414074 + y 284.8975707321614 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 237 + pajek_id 237 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1446.3792419244076 + y 1813.9029462286976 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 238 + pajek_id 238 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1813.9462106455926 + y 947.4822230702299 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 239 + pajek_id 239 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1428.5911518460912 + y 1609.8340596280282 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 240 + pajek_id 240 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1005.3650634855937 + y 882.2530156601648 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 241 + pajek_id 241 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1970.4155162426391 + y 1125.8976010185038 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 242 + pajek_id 242 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 240.57076448405542 + y 1473.723263945339 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 243 + pajek_id 243 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2046.1993784054494 + y 950.6121816835345 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 244 + pajek_id 244 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2808.307733786458 + y 1514.739154198832 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 245 + pajek_id 245 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1882.8938446652257 + y 1459.0281000095843 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 246 + pajek_id 246 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1723.9114037847546 + y 2365.644132764209 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 247 + pajek_id 247 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1936.717394034969 + y 1594.3192138208242 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 248 + pajek_id 248 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1971.7509493535508 + y 1179.4845850946012 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 249 + pajek_id 249 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1058.6250365444143 + y 859.7134012319751 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 250 + pajek_id 250 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1875.0949016123318 + y 2018.8968281970356 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 251 + pajek_id 251 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 802.2218018782783 + y 830.0503347776802 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 252 + pajek_id 252 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 813.0528123889172 + y 1656.3453211681867 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 253 + pajek_id 253 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1273.6722755380645 + y 562.4903627029978 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 254 + pajek_id 254 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 738.6225904711797 + y 1832.437257453023 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 255 + pajek_id 255 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2123.755229836545 + y 2672.877537298277 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 256 + pajek_id 256 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 766.238178017943 + y 627.4085851267696 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 257 + pajek_id 257 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1129.8317234871274 + y 1757.6767114954823 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 258 + pajek_id 258 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2009.7762232303267 + y 2041.0971651622217 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 259 + pajek_id 259 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1736.9465300050063 + y 1793.4455313056224 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 260 + pajek_id 260 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 648.0899197694613 + y 1133.071910642336 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 261 + pajek_id 261 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2673.608535682633 + y 1969.3166527926637 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 262 + pajek_id 262 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1190.4241821550581 + y 1456.8778384709221 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 263 + pajek_id 263 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1773.3304812765168 + y 1171.6981943217245 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 264 + pajek_id 264 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2455.8689870091684 + y 1698.2588839027976 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 265 + pajek_id 265 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1572.4184904317372 + y 1079.9405584556314 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 266 + pajek_id 266 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 930.5993117411441 + y 932.4301787306301 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 267 + pajek_id 267 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1241.016109181929 + y 1641.851386078472 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 268 + pajek_id 268 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1778.3112226979574 + y 1527.5198182466306 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 269 + pajek_id 269 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1997.6945206439827 + y 1435.167335502786 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 270 + pajek_id 270 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2928.2834579168007 + y 1108.202244706911 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 271 + pajek_id 271 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1549.1458457473145 + y 592.3498910478805 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 272 + pajek_id 272 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2567.1609182049815 + y 349.9728983492399 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 273 + pajek_id 273 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1790.3664691634244 + y 2391.926302478362 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 274 + pajek_id 274 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1156.9233946634465 + y 1363.0451223083915 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 275 + pajek_id 275 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 856.1024353157368 + y 2058.0580043741106 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 276 + pajek_id 276 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2007.3448524911623 + y 955.2249749444019 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 277 + pajek_id 277 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1867.826843063508 + y 1168.1178614284738 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 278 + pajek_id 278 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1849.7065836818551 + y 1931.1333235795955 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 279 + pajek_id 279 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1260.0763722109286 + y 655.2169595822215 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 280 + pajek_id 280 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1899.1104082490497 + y 1614.8129891919102 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 281 + pajek_id 281 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2378.43114046961 + y 2184.529789498435 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 282 + pajek_id 282 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2040.929028434561 + y 2329.0083925520726 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 283 + pajek_id 283 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1329.822091272441 + y 817.7805081038614 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 284 + pajek_id 284 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1916.5095601095395 + y 1315.8369929397447 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 285 + pajek_id 285 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1540.8732018426379 + y 1757.2830276053164 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 286 + pajek_id 286 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1497.5518877310492 + y 2332.209587716714 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 287 + pajek_id 287 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1820.876610989953 + y 1705.7800792711614 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 288 + pajek_id 288 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2053.621424690008 + y 137.4950984709352 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 289 + pajek_id 289 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2288.638168809773 + y 1661.1373438648448 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 290 + pajek_id 290 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2521.628031511117 + y 1112.8442155271284 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 291 + pajek_id 291 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2621.075261275747 + y 1040.7003954194217 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 292 + pajek_id 292 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1489.7226658046911 + y 1212.598420726727 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 293 + pajek_id 293 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1344.039251806568 + y 765.4921416388333 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 294 + pajek_id 294 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2783.106085646018 + y 1011.1576483698651 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 295 + pajek_id 295 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 666.034857878941 + y 1196.1544941612838 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 296 + pajek_id 296 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1069.4593629564115 + y 1627.9059240200613 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 297 + pajek_id 297 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1798.2247140891636 + y 1428.1375539568382 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 298 + pajek_id 298 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1934.1343683875075 + y 2404.2315045912405 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 299 + pajek_id 299 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2699.851785344458 + y 427.8558563028148 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 300 + pajek_id 300 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 834.2031874852718 + y 250.70469068286297 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 301 + pajek_id 301 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1004.0710874574961 + y 1280.167160042513 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 302 + pajek_id 302 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1750.4516583745296 + y 1471.2162955489407 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 303 + pajek_id 303 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2401.7820655598725 + y 2272.1863557268275 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 304 + pajek_id 304 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1814.6823768957051 + y 2071.5062836539637 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 305 + pajek_id 305 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2520.536274654057 + y 992.8636618688267 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 306 + pajek_id 306 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2265.0881548319567 + y 2065.5837863656484 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 307 + pajek_id 307 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1257.8172960656739 + y 803.4108171125971 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 308 + pajek_id 308 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 776.7856178664061 + y 1694.4563434703907 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 309 + pajek_id 309 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1440.886631358504 + y 1532.750033969016 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 310 + pajek_id 310 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1989.010230552772 + y 259.2322753906619 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 311 + pajek_id 311 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 793.6486929322533 + y 1180.108345062422 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 312 + pajek_id 312 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1917.539646877893 + y 2281.8557999514537 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 313 + pajek_id 313 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 867.9822424379655 + y 1709.027298137467 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 314 + pajek_id 314 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1484.2011650524655 + y 1345.1479429348788 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 315 + pajek_id 315 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1076.084829910138 + y 996.0235144558553 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 316 + pajek_id 316 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1693.090850412172 + y 2090.5966253636116 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 317 + pajek_id 317 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2037.1290633056465 + y 369.80076511683393 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 318 + pajek_id 318 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1007.8277192737382 + y 1754.1325273022699 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 319 + pajek_id 319 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2172.028629136008 + y 1461.0364064098994 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 320 + pajek_id 320 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2257.1227609527 + y 1310.8862977736107 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 321 + pajek_id 321 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1300.745991888025 + y 2187.297908294803 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 322 + pajek_id 322 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2204.6686322693918 + y 1410.994870895594 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 323 + pajek_id 323 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 864.8355633586339 + y 1982.7204827008345 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 324 + pajek_id 324 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 800.0003105548103 + y 1923.7791435231852 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 325 + pajek_id 325 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1024.7502660900132 + y 1366.1758015615299 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 326 + pajek_id 326 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2050.7149391093694 + y 1257.3982758996383 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 327 + pajek_id 327 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 960.7821525481202 + y 1584.4968382633942 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 328 + pajek_id 328 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1124.4061711877166 + y 1046.726994002646 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 329 + pajek_id 329 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1108.4893044148541 + y 1194.3431578903087 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 330 + pajek_id 330 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1100.133655193655 + y 1137.6918022343907 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 331 + pajek_id 331 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1760.6862781934046 + y 1320.6513715309195 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 332 + pajek_id 332 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1200.2523322538245 + y 1002.7964728390644 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 333 + pajek_id 333 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1181.4892595539825 + y 1225.6989123360675 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 334 + pajek_id 334 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1868.4127438749463 + y 1117.6967188028786 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 335 + pajek_id 335 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2168.6794851454647 + y 1162.2427344452735 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 336 + pajek_id 336 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1920.9638225147678 + y 876.5150707247215 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 337 + pajek_id 337 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2920.808088394186 + y 892.3685934633982 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 338 + pajek_id 338 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1645.909927183584 + y 1471.9956590731072 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 339 + pajek_id 339 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1447.1109049135396 + y 1746.1534799232427 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 340 + pajek_id 340 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1303.087697302223 + y 1599.75182872408 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 341 + pajek_id 341 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1404.1964183968635 + y 1732.988309973422 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 342 + pajek_id 342 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 188.7586938483705 + y 732.4710661793797 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 343 + pajek_id 343 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 237.5145668340565 + y 798.209667685809 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 344 + pajek_id 344 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 655.6090365411286 + y 768.8237020380398 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 345 + pajek_id 345 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1239.593772491194 + y 142.24994629451373 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 346 + pajek_id 346 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 668.4582174721975 + y 1570.710895937615 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 347 + pajek_id 347 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 704.1732692312117 + y 1623.8128247520694 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 348 + pajek_id 348 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1806.5024342076917 + y 1845.9002776470725 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 349 + pajek_id 349 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1572.0491307665409 + y 1632.2321415433307 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 350 + pajek_id 350 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2170.491596866099 + y 252.15493902189132 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 351 + pajek_id 351 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2236.6106720779644 + y 313.9614539100346 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 352 + pajek_id 352 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1956.787709026074 + y 478.6286472297293 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 353 + pajek_id 353 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1521.6247356278914 + y 651.1377056441239 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 354 + pajek_id 354 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2673.4749982408534 + y 1517.3687949519558 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 355 + pajek_id 355 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2462.8285772682266 + y 853.132399611773 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 356 + pajek_id 356 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2723.74809870115 + y 928.6302426931661 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 357 + pajek_id 357 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1370.7051182886262 + y 1487.7369332080375 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 358 + pajek_id 358 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 468.7736750192556 + y 1245.6923887724063 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 359 + pajek_id 359 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 769.1240346507418 + y 1297.5083732935518 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 360 + pajek_id 360 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1281.6747231335723 + y 1222.571355135779 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 361 + pajek_id 361 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2579.810673602955 + y 486.0242869026378 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 362 + pajek_id 362 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1625.153907135859 + y 1657.7991036276171 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 363 + pajek_id 363 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1685.4668204197178 + y 1675.1432793501972 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 364 + pajek_id 364 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1649.065379741583 + y 1710.3631889761837 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 365 + pajek_id 365 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1735.2434575622904 + y 1652.0103910358575 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 366 + pajek_id 366 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1546.6380216667462 + y 1660.4291808801559 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 367 + pajek_id 367 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1592.959070056042 + y 1701.930864398132 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 368 + pajek_id 368 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2000.4352383965368 + y 1758.4816008564803 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 369 + pajek_id 369 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1468.5107210693257 + y 1274.5523522286858 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 370 + pajek_id 370 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1343.841518355971 + y 868.6992458482348 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 371 + pajek_id 371 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 956.4416724575727 + y 1542.5109738519532 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 372 + pajek_id 372 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1033.5848153857899 + y 2047.0346481519837 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 373 + pajek_id 373 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1145.9845954789732 + y 2010.3598901708774 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 374 + pajek_id 374 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 966.9695596108811 + y 2038.5494954424362 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 375 + pajek_id 375 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1101.5378289239488 + y 2056.772094668872 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 376 + pajek_id 376 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1015.5518645355227 + y 498.21676713384437 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 377 + pajek_id 377 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1108.5018026732564 + y 1836.2444968902573 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 378 + pajek_id 378 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1050.8064474323255 + y 1820.5838099325315 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 379 + pajek_id 379 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1022.4653344068506 + y 1715.6126995231655 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 380 + pajek_id 380 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 973.3911705488091 + y 1656.6045446044554 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 381 + pajek_id 381 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 980.1312729019277 + y 1790.1875755402975 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 382 + pajek_id 382 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1165.9502913921285 + y 1848.0553893620186 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 383 + pajek_id 383 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1847.4512820966625 + y 997.8047505299883 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 384 + pajek_id 384 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1834.8709235195802 + y 1082.3420824375842 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 385 + pajek_id 385 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1926.272882956845 + y 1130.2140856000237 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 386 + pajek_id 386 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2019.5057069987238 + y 1083.2924715168538 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 387 + pajek_id 387 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 340.467937490798 + y 1722.2588619668122 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 388 + pajek_id 388 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 613.237652883032 + y 1579.9427905965279 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 389 + pajek_id 389 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1655.1932187894404 + y 1782.2310536598284 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 390 + pajek_id 390 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1637.2667690847445 + y 952.3525949687174 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 391 + pajek_id 391 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2630.804204930251 + y 2213.7673865428937 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 392 + pajek_id 392 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1080.8078508715175 + y 1570.3664421378583 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 393 + pajek_id 393 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2234.068836486567 + y 1160.6502978141489 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 394 + pajek_id 394 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1086.7948765031201 + y 76.91119774421213 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 395 + pajek_id 395 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2461.9112093928975 + y 1766.6838415805391 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 396 + pajek_id 396 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 113.1199288710568 + y 369.28510273478156 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 397 + pajek_id 397 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1776.1814775671203 + y 1971.90651207382 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 398 + pajek_id 398 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1707.0558465571435 + y 1296.0087781780164 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 399 + pajek_id 399 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1417.7718529314445 + y 1350.7244506853776 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 400 + pajek_id 400 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2125.52060844245 + y 1048.4849048770884 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 401 + pajek_id 401 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1552.3770468848625 + y 2260.559438155617 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 402 + pajek_id 402 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1874.1651337345234 + y 1245.0945400298474 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 403 + pajek_id 403 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1256.6383628219503 + y 1450.7738470869801 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 404 + pajek_id 404 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2259.967596935999 + y 2120.7466929344328 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 405 + pajek_id 405 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2500.5496931980915 + y 1966.736685021926 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 406 + pajek_id 406 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2347.7927648395157 + y 2091.6701739856917 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 407 + pajek_id 407 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2392.889146581768 + y 2044.8922015795006 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 408 + pajek_id 408 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2417.761515347872 + y 1975.5515523680338 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 409 + pajek_id 409 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1793.9182626491624 + y 1627.666690778881 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 410 + pajek_id 410 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 719.1430254147674 + y 1486.956454607635 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 411 + pajek_id 411 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 724.2454716778103 + y 1551.3831943720716 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 412 + pajek_id 412 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2447.6879968351877 + y 1876.5514180960204 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 413 + pajek_id 413 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2091.9643045079483 + y 1974.8640522416667 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 414 + pajek_id 414 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2028.15537010984 + y 1956.056476995101 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 415 + pajek_id 415 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1984.2252245737018 + y 1908.623346940285 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 416 + pajek_id 416 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2119.7472033124163 + y 1865.6311815257598 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 417 + pajek_id 417 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2130.68571853772 + y 1928.6302578749373 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 418 + pajek_id 418 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2122.510896875806 + y 1780.9007711280406 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 419 + pajek_id 419 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2066.857133577992 + y 1911.002176703526 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 420 + pajek_id 420 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2174.073650971839 + y 1808.4465867530826 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 421 + pajek_id 421 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2173.188445315479 + y 1879.1912761247552 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 422 + pajek_id 422 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2445.130066970032 + y 1152.7800567449078 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 423 + pajek_id 423 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2355.4692035510784 + y 1402.5903362442382 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 424 + pajek_id 424 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2415.2373515095965 + y 1088.9498827129119 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 425 + pajek_id 425 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2039.5995058528129 + y 1430.5751740405808 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 426 + pajek_id 426 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 322.6815092460105 + y 2116.2903817807914 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 427 + pajek_id 427 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 268.5119994462548 + y 2056.087634484369 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 428 + pajek_id 428 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1146.757825786496 + y 364.2656095233129 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 429 + pajek_id 429 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1489.2719624004453 + y 693.8971583258162 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 430 + pajek_id 430 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1827.8677422310066 + y 766.7899007728367 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 431 + pajek_id 431 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1798.3747778112622 + y 1215.8365936661658 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 432 + pajek_id 432 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 804.3580561584004 + y 501.9583186324991 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 433 + pajek_id 433 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 849.2647555481542 + y 434.2847659573615 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 434 + pajek_id 434 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2328.3994872753374 + y 2321.663189777115 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 435 + pajek_id 435 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 618.9825732416654 + y 1813.9348120438804 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 436 + pajek_id 436 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 700.4298252161705 + y 1333.1902810428091 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 437 + pajek_id 437 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1395.7113829826137 + y 1284.9840905117753 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 438 + pajek_id 438 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2630.3138122865585 + y 1172.8988923967477 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 439 + pajek_id 439 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2615.848167339149 + y 1246.8020908359208 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 440 + pajek_id 440 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 469.43123730699017 + y 854.8438020056724 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 441 + pajek_id 441 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2116.96992696925 + y 1379.4358280316942 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 442 + pajek_id 442 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2081.349871481623 + y 1329.7245666590386 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 443 + pajek_id 443 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2424.702556920728 + y 768.839004481539 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 444 + pajek_id 444 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 890.6313761901736 + y 115.79231393666316 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 445 + pajek_id 445 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 857.1356243649586 + y 174.88311586144653 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 446 + pajek_id 446 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 512.8629774244184 + y 2201.527945647691 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 447 + pajek_id 447 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 677.7488039882435 + y 1909.537866326766 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 448 + pajek_id 448 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1338.956871819991 + y 1010.8829829830978 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 449 + pajek_id 449 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1324.088243934198 + y 1729.0798093126218 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 450 + pajek_id 450 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1724.263819989563 + y 504.51288018417335 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 451 + pajek_id 451 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1910.6105654550115 + y 630.6123921072538 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 452 + pajek_id 452 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1710.4548801725487 + y 647.7553354187357 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 453 + pajek_id 453 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1702.9391298385015 + y 563.411307161135 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 454 + pajek_id 454 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1826.116078147204 + y 450.3392482519506 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 455 + pajek_id 455 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2011.5270490887758 + y 760.825852289636 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 456 + pajek_id 456 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2101.9753242282413 + y 581.5866515110404 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 457 + pajek_id 457 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2603.3686351996375 + y 1409.84659720882 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 458 + pajek_id 458 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2438.056345618056 + y 1523.7553993407314 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 459 + pajek_id 459 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2331.6849268576207 + y 1134.766411504912 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 460 + pajek_id 460 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1059.0576214306932 + y 2264.1041145319637 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 461 + pajek_id 461 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1458.141237363875 + y 755.4394205573406 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 462 + pajek_id 462 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 424.1436855406298 + y 1477.224543730106 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 463 + pajek_id 463 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 378.7154942468852 + y 1401.5037756061158 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 464 + pajek_id 464 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 314.0529479996145 + y 1373.0410118674613 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 465 + pajek_id 465 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 353.0119560198315 + y 1455.904690398989 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 466 + pajek_id 466 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 834.3766918623855 + y 1291.1793247114124 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 467 + pajek_id 467 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 893.5300096467302 + y 1847.377115763661 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 468 + pajek_id 468 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 716.2809799836317 + y 2178.244847004791 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 469 + pajek_id 469 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2541.4812097684 + y 2043.553501917624 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 470 + pajek_id 470 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1119.6037534804425 + y 1102.2487155380616 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 471 + pajek_id 471 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1007.8554543482325 + y 1148.2192014655018 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 472 + pajek_id 472 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2355.376017232971 + y 1455.616264520982 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 473 + pajek_id 473 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2394.6586276164862 + y 1491.7526626843892 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 474 + pajek_id 474 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2248.1811205504373 + y 1647.7634009017388 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 475 + pajek_id 475 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2337.1166010827837 + y 1520.6716608448314 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 476 + pajek_id 476 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2420.759607231811 + y 1589.229118968443 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 477 + pajek_id 477 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2314.5533268916042 + y 1604.0297855841632 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 478 + pajek_id 478 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2364.2202931300694 + y 1575.671922904723 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 479 + pajek_id 479 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2194.5964587031503 + y 1638.225011658421 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 480 + pajek_id 480 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1065.4992788010986 + y 1464.6555423148318 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 481 + pajek_id 481 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 968.0925172159282 + y 1354.4290172504502 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 482 + pajek_id 482 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1126.8845029318243 + y 1435.5731026238109 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 483 + pajek_id 483 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1213.8500385478933 + y 1383.2655755080937 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 484 + pajek_id 484 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1391.466199058675 + y 2589.0242705868145 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 485 + pajek_id 485 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1324.9339892036385 + y 2618.7726752706 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 486 + pajek_id 486 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1447.1572287025065 + y 927.5802766521502 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 487 + pajek_id 487 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2147.787079263979 + y 2593.4264109946484 + w 20.0 + h 20.0 + fill "#FFFF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 488 + pajek_id 488 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2020.4864930201384 + y 2667.000204943657 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 489 + pajek_id 489 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2455.283559589994 + y 2086.657483037342 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 490 + pajek_id 490 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1682.851876497575 + y 1583.6120931079872 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 491 + pajek_id 491 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1161.1187083008704 + y 1611.7393863381692 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 492 + pajek_id 492 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1041.2626018954427 + y 1598.954971993218 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 493 + pajek_id 493 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2297.354570397635 + y 534.3652679637769 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 494 + pajek_id 494 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 526.5370388426392 + y 485.54459385039985 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 495 + pajek_id 495 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 560.2941765427282 + y 402.56083072436417 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 496 + pajek_id 496 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 377.08394387788996 + y 1333.3317088869094 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 497 + pajek_id 497 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 489.3047686961877 + y 1939.8674034964001 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 498 + pajek_id 498 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 527.233322511409 + y 2017.0516767470162 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 499 + pajek_id 499 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1605.5668452162006 + y 1992.166283565707 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 500 + pajek_id 500 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1546.0840293799524 + y 1955.4015275314973 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 501 + pajek_id 501 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2656.759269426316 + y 1685.5061982513696 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 502 + pajek_id 502 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1728.2354096255438 + y 1051.4437767810607 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 503 + pajek_id 503 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 317.98253615853616 + y 835.2488823603016 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 504 + pajek_id 504 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1227.6068253899532 + y 1819.6331253463359 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 505 + pajek_id 505 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1574.3747014862265 + y 289.21933118032086 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 506 + pajek_id 506 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1436.7167412577667 + y 2136.3809474284844 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 507 + pajek_id 507 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1928.2290848617536 + y 1695.8756254197222 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 508 + pajek_id 508 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2229.8166656736694 + y 1842.5176093374575 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 509 + pajek_id 509 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2191.4931676161536 + y 1969.3723460631686 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 510 + pajek_id 510 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2404.7934790895088 + y 917.1422166878989 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 511 + pajek_id 511 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2395.2429436891007 + y 834.027810518057 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 512 + pajek_id 512 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1638.416583359785 + y 1075.9248111470263 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 513 + pajek_id 513 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1117.2425662770952 + y 945.1325831390579 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 514 + pajek_id 514 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1071.8339051492999 + y 667.2084929230319 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 515 + pajek_id 515 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2080.1550476846883 + y 2248.7722822540536 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 516 + pajek_id 516 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 941.7035591125789 + y 2315.12355349285 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 517 + pajek_id 517 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 864.0401900606075 + y 854.7476458360196 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 518 + pajek_id 518 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1451.1619559522182 + y 1947.3205327227465 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 519 + pajek_id 519 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1481.5993172162407 + y 1688.7490679204407 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 520 + pajek_id 520 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 132.29183753554184 + y 1549.9709751408773 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 521 + pajek_id 521 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 201.92596700389458 + y 1601.853692109065 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 522 + pajek_id 522 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2153.1192264901847 + y 822.9210553334786 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 523 + pajek_id 523 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 640.2772506993291 + y 1675.9420021748028 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 524 + pajek_id 524 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1320.8511741047305 + y 408.77871976114494 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 525 + pajek_id 525 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2213.924926553872 + y 2763.501088516637 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 526 + pajek_id 526 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2074.4442713188187 + y 2170.28081217305 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 527 + pajek_id 527 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1907.281150461828 + y 1756.8956641399836 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 528 + pajek_id 528 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2125.030039415664 + y 2128.3283642176266 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 529 + pajek_id 529 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1748.248950250427 + y 1911.7557662270228 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 530 + pajek_id 530 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1150.8356799670266 + y 1544.1121345992892 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 531 + pajek_id 531 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1477.1689178603895 + y 1147.0096180737971 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 532 + pajek_id 532 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1458.9597650345672 + y 1060.9858986563445 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 533 + pajek_id 533 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1495.8280010142782 + y 989.2245050486312 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 534 + pajek_id 534 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 784.4777027529236 + y 948.7566853266054 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 535 + pajek_id 535 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2110.665526987148 + y 1497.723078348779 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 536 + pajek_id 536 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 3038.33263338064 + y 1192.8113918381189 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 537 + pajek_id 537 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1603.7304792610369 + y 454.1950074099879 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 538 + pajek_id 538 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1801.2035133048555 + y 2119.4411185171184 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 539 + pajek_id 539 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1950.4501795255455 + y 2049.3079413070072 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 540 + pajek_id 540 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1757.897607156828 + y 2049.7669278996045 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 541 + pajek_id 541 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1854.7360726993138 + y 1393.7369312635797 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 542 + pajek_id 542 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1415.8484373759234 + y 1900.9653905466644 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 543 + pajek_id 543 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1497.5005911357582 + y 2480.683702039123 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 544 + pajek_id 544 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 719.9288183455253 + y 236.78163159716667 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 545 + pajek_id 545 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2509.6237885742785 + y 2373.522488677848 + w 20.0 + h 20.0 + fill "#FF3333" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 546 + pajek_id 546 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2436.169862983399 + y 2416.0522801899683 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 547 + pajek_id 547 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 647.1888372458554 + y 1741.9224475898036 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 548 + pajek_id 548 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 681.8502532202343 + y 1799.6304470782582 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 549 + pajek_id 549 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1985.5267000858494 + y 2369.7344325668428 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 550 + pajek_id 550 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1991.106100021963 + y 2440.329057425812 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 551 + pajek_id 551 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1931.1619344063192 + y 2470.578249185151 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 552 + pajek_id 552 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1875.3109201344084 + y 2408.7968384052087 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 553 + pajek_id 553 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1587.9274187718331 + y 1318.0146867000844 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 554 + pajek_id 554 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 930.2559142741628 + y 1891.3731392078669 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 555 + pajek_id 555 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1227.5755919224916 + y 2306.541693351298 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 556 + pajek_id 556 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1304.4750058932211 + y 2321.289347146842 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 557 + pajek_id 557 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 2217.1358311583554 + y 1273.7535975697697 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + node [ + id 558 + pajek_id 558 + label "" + labelgraphics [ + anchor "c" + fontName "Tahoma" + alignment "left" + fontSize 13 + fontStyle "plain" + color "#000000" + type "text" + ] + graphics [ + x 1066.387215640596 + y 1714.3761855178568 + w 20.0 + h 20.0 + fill "#00FF00" + outline "#000000" + frameThickness 3.0 + rounding 5.0 + gradient 0.0 + type "oval" + ] + ] + edge [ + id 1 + source 1 + target 87 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 2 + source 1 + target 223 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 3 + source 1 + target 266 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 4 + source 1 + target 328 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 5 + source 1 + target 329 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 6 + source 1 + target 330 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 7 + source 1 + target 331 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 8 + source 1 + target 332 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 9 + source 1 + target 333 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 10 + source 2 + target 334 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 11 + source 2 + target 335 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 12 + source 3 + target 172 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 13 + source 3 + target 188 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 14 + source 3 + target 257 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 15 + source 4 + target 225 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 16 + source 5 + target 175 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 17 + source 6 + target 143 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 18 + source 7 + target 118 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 19 + source 7 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 20 + source 7 + target 336 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 21 + source 8 + target 30 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 22 + source 8 + target 337 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 23 + source 9 + target 338 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 24 + source 10 + target 198 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 25 + source 11 + target 261 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 26 + source 12 + target 66 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 27 + source 12 + target 114 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 28 + source 12 + target 144 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 29 + source 12 + target 189 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 30 + source 12 + target 237 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 31 + source 12 + target 239 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 32 + source 12 + target 267 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 33 + source 12 + target 268 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 34 + source 12 + target 339 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 35 + source 12 + target 340 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 36 + source 12 + target 341 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 37 + source 13 + target 15 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 38 + source 13 + target 85 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 39 + source 14 + target 212 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 40 + source 15 + target 342 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 41 + source 15 + target 343 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 42 + source 15 + target 344 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 43 + source 16 + target 143 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 44 + source 16 + target 191 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 45 + source 17 + target 54 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 46 + source 17 + target 345 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 47 + source 18 + target 100 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 48 + source 18 + target 346 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 49 + source 18 + target 347 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 50 + source 19 + target 267 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 51 + source 20 + target 348 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 52 + source 20 + target 349 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 53 + source 21 + target 81 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 54 + source 22 + target 65 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 55 + source 23 + target 140 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 56 + source 23 + target 350 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 57 + source 23 + target 351 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 58 + source 23 + target 352 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 59 + source 24 + target 217 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 60 + source 25 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 61 + source 26 + target 119 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 62 + source 26 + target 353 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 63 + source 27 + target 353 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 64 + source 28 + target 178 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 65 + source 29 + target 148 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 66 + source 29 + target 175 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 67 + source 29 + target 206 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 68 + source 29 + target 354 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 69 + source 30 + target 212 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 70 + source 30 + target 294 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 71 + source 30 + target 355 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 72 + source 30 + target 356 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 73 + source 31 + target 334 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 74 + source 32 + target 353 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 75 + source 33 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 76 + source 34 + target 217 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 77 + source 34 + target 220 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 78 + source 34 + target 262 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 79 + source 34 + target 357 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 80 + source 35 + target 358 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 81 + source 35 + target 359 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 82 + source 36 + target 342 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 83 + source 37 + target 162 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 84 + source 38 + target 311 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 85 + source 39 + target 174 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 86 + source 40 + target 228 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 87 + source 41 + target 311 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 88 + source 42 + target 53 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 89 + source 43 + target 265 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 90 + source 43 + target 360 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 91 + source 44 + target 361 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 92 + source 45 + target 53 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 93 + source 46 + target 118 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 94 + source 46 + target 285 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 95 + source 46 + target 362 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 96 + source 46 + target 363 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 97 + source 46 + target 364 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 98 + source 46 + target 365 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 99 + source 46 + target 366 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 100 + source 46 + target 367 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 101 + source 46 + target 368 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 102 + source 46 + target 369 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 103 + source 47 + target 78 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 104 + source 48 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 105 + source 49 + target 167 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 106 + source 49 + target 370 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 107 + source 50 + target 371 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 108 + source 51 + target 155 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 109 + source 51 + target 233 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 110 + source 51 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 111 + source 51 + target 372 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 112 + source 51 + target 373 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 113 + source 51 + target 374 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 114 + source 51 + target 375 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 115 + source 52 + target 126 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 116 + source 52 + target 376 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 117 + source 53 + target 62 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 118 + source 53 + target 66 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 119 + source 53 + target 371 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 120 + source 53 + target 377 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 121 + source 53 + target 378 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 122 + source 53 + target 379 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 123 + source 53 + target 380 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 124 + source 53 + target 381 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 125 + source 53 + target 382 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 126 + source 54 + target 126 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 127 + source 54 + target 138 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 128 + source 55 + target 143 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 129 + source 56 + target 147 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 130 + source 56 + target 383 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 131 + source 56 + target 384 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 132 + source 56 + target 385 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 133 + source 56 + target 386 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 134 + source 57 + target 283 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 135 + source 58 + target 210 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 136 + source 59 + target 387 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 137 + source 59 + target 388 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 138 + source 60 + target 189 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 139 + source 61 + target 93 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 140 + source 61 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 141 + source 62 + target 110 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 142 + source 62 + target 265 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 143 + source 62 + target 278 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 144 + source 62 + target 338 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 145 + source 62 + target 389 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 146 + source 63 + target 215 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 147 + source 64 + target 97 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 148 + source 64 + target 99 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 149 + source 65 + target 158 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 150 + source 65 + target 222 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 151 + source 65 + target 297 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 152 + source 65 + target 390 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 153 + source 66 + target 127 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 154 + source 66 + target 340 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 155 + source 67 + target 181 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 156 + source 68 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 157 + source 69 + target 185 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 158 + source 69 + target 391 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 159 + source 70 + target 162 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 160 + source 71 + target 327 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 161 + source 71 + target 392 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 162 + source 72 + target 286 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 163 + source 73 + target 113 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 164 + source 74 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 165 + source 75 + target 247 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 166 + source 75 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 167 + source 75 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 168 + source 75 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 169 + source 76 + target 85 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 170 + source 77 + target 87 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 171 + source 78 + target 393 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 172 + source 79 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 173 + source 80 + target 147 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 174 + source 81 + target 117 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 175 + source 81 + target 394 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 176 + source 82 + target 138 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 177 + source 83 + target 194 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 178 + source 83 + target 235 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 179 + source 84 + target 171 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 180 + source 84 + target 395 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 181 + source 85 + target 396 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 182 + source 86 + target 209 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 183 + source 87 + target 118 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 184 + source 87 + target 145 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 185 + source 87 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 186 + source 87 + target 369 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 187 + source 88 + target 318 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 188 + source 89 + target 397 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 189 + source 90 + target 143 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 190 + source 91 + target 215 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 191 + source 92 + target 110 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 192 + source 93 + target 111 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 193 + source 94 + target 126 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 194 + source 94 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 195 + source 95 + target 392 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 196 + source 95 + target 398 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 197 + source 95 + target 399 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 198 + source 96 + target 111 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 199 + source 96 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 200 + source 96 + target 398 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 201 + source 96 + target 400 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 202 + source 97 + target 286 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 203 + source 97 + target 401 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 204 + source 98 + target 143 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 205 + source 99 + target 204 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 206 + source 99 + target 222 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 207 + source 99 + target 402 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 208 + source 100 + target 129 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 209 + source 100 + target 227 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 210 + source 100 + target 340 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 211 + source 100 + target 403 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 212 + source 101 + target 318 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 213 + source 101 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 214 + source 102 + target 227 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 215 + source 103 + target 121 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 216 + source 103 + target 280 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 217 + source 103 + target 404 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 218 + source 103 + target 405 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 219 + source 103 + target 406 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 220 + source 103 + target 407 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 221 + source 103 + target 408 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 222 + source 104 + target 117 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 223 + source 105 + target 156 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 224 + source 106 + target 188 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 225 + source 106 + target 252 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 226 + source 106 + target 257 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 227 + source 106 + target 318 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 228 + source 107 + target 409 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 229 + source 108 + target 267 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 230 + source 108 + target 388 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 231 + source 108 + target 410 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 232 + source 108 + target 411 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 233 + source 109 + target 220 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 234 + source 109 + target 412 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 235 + source 110 + target 217 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 236 + source 110 + target 278 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 237 + source 110 + target 289 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 238 + source 110 + target 413 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 239 + source 110 + target 414 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 240 + source 110 + target 415 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 241 + source 110 + target 416 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 242 + source 110 + target 417 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 243 + source 110 + target 418 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 244 + source 110 + target 419 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 245 + source 110 + target 420 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 246 + source 110 + target 421 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 247 + source 111 + target 422 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 248 + source 111 + target 423 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 249 + source 111 + target 424 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 250 + source 112 + target 425 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 251 + source 113 + target 202 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 252 + source 113 + target 426 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 253 + source 113 + target 427 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 254 + source 114 + target 142 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 255 + source 114 + target 239 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 256 + source 115 + target 275 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 257 + source 116 + target 352 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 258 + source 117 + target 253 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 259 + source 117 + target 428 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 260 + source 117 + target 429 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 261 + source 118 + target 143 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 262 + source 118 + target 212 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 263 + source 118 + target 276 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 264 + source 118 + target 352 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 265 + source 118 + target 353 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 266 + source 118 + target 429 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 267 + source 118 + target 430 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 268 + source 118 + target 431 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 269 + source 119 + target 256 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 270 + source 119 + target 432 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 271 + source 119 + target 433 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 272 + source 120 + target 147 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 273 + source 121 + target 434 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 274 + source 122 + target 202 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 275 + source 122 + target 392 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 276 + source 122 + target 435 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 277 + source 123 + target 129 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 278 + source 123 + target 436 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 279 + source 123 + target 437 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 280 + source 124 + target 393 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 281 + source 124 + target 438 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 282 + source 124 + target 439 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 283 + source 125 + target 258 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 284 + source 126 + target 235 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 285 + source 127 + target 141 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 286 + source 127 + target 217 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 287 + source 127 + target 239 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 288 + source 127 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 289 + source 127 + target 309 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 290 + source 128 + target 440 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 291 + source 129 + target 162 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 292 + source 130 + target 263 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 293 + source 130 + target 320 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 294 + source 130 + target 441 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 295 + source 130 + target 442 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 296 + source 131 + target 429 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 297 + source 132 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 298 + source 133 + target 138 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 299 + source 134 + target 310 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 300 + source 135 + target 234 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 301 + source 135 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 302 + source 135 + target 443 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 303 + source 136 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 304 + source 137 + target 210 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 305 + source 137 + target 311 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 306 + source 138 + target 300 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 307 + source 138 + target 444 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 308 + source 138 + target 445 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 309 + source 139 + target 446 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 310 + source 139 + target 447 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 311 + source 140 + target 147 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 312 + source 141 + target 227 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 313 + source 141 + target 448 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 314 + source 142 + target 237 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 315 + source 142 + target 239 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 316 + source 142 + target 267 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 317 + source 142 + target 321 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 318 + source 142 + target 339 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 319 + source 142 + target 340 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 320 + source 142 + target 341 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 321 + source 142 + target 449 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 322 + source 143 + target 228 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 323 + source 143 + target 450 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 324 + source 143 + target 451 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 325 + source 143 + target 452 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 326 + source 143 + target 453 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 327 + source 143 + target 454 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 328 + source 144 + target 239 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 329 + source 145 + target 174 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 330 + source 146 + target 220 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 331 + source 146 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 332 + source 147 + target 455 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 333 + source 147 + target 456 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 334 + source 148 + target 320 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 335 + source 148 + target 457 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 336 + source 148 + target 458 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 337 + source 149 + target 314 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 338 + source 150 + target 305 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 339 + source 151 + target 291 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 340 + source 151 + target 459 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 341 + source 152 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 342 + source 153 + target 188 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 343 + source 153 + target 448 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 344 + source 154 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 345 + source 155 + target 460 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 346 + source 156 + target 246 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 347 + source 157 + target 461 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 348 + source 158 + target 461 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 349 + source 159 + target 349 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 350 + source 160 + target 175 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 351 + source 161 + target 357 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 352 + source 161 + target 359 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 353 + source 162 + target 436 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 354 + source 162 + target 462 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 355 + source 162 + target 463 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 356 + source 162 + target 464 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 357 + source 162 + target 465 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 358 + source 163 + target 227 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 359 + source 164 + target 262 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 360 + source 164 + target 359 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 361 + source 164 + target 466 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 362 + source 165 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 363 + source 166 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 364 + source 167 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 365 + source 168 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 366 + source 168 + target 468 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 367 + source 169 + target 180 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 368 + source 170 + target 469 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 369 + source 171 + target 175 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 370 + source 171 + target 206 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 371 + source 171 + target 395 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 372 + source 172 + target 187 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 373 + source 173 + target 470 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 374 + source 174 + target 266 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 375 + source 174 + target 369 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 376 + source 174 + target 471 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 377 + source 175 + target 280 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 378 + source 175 + target 331 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 379 + source 175 + target 458 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 380 + source 175 + target 472 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 381 + source 175 + target 473 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 382 + source 175 + target 474 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 383 + source 175 + target 475 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 384 + source 175 + target 476 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 385 + source 175 + target 477 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 386 + source 175 + target 478 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 387 + source 175 + target 479 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 388 + source 176 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 389 + source 177 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 390 + source 178 + target 225 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 391 + source 178 + target 227 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 392 + source 178 + target 296 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 393 + source 178 + target 480 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 394 + source 178 + target 481 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 395 + source 178 + target 482 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 396 + source 178 + target 483 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 397 + source 179 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 398 + source 180 + target 321 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 399 + source 180 + target 484 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 400 + source 180 + target 485 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 401 + source 181 + target 222 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 402 + source 181 + target 225 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 403 + source 181 + target 227 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 404 + source 181 + target 486 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 405 + source 182 + target 255 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 406 + source 182 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 407 + source 182 + target 487 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 408 + source 182 + target 488 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 409 + source 183 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 410 + source 184 + target 387 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 411 + source 185 + target 306 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 412 + source 185 + target 368 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 413 + source 185 + target 469 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 414 + source 185 + target 489 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 415 + source 186 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 416 + source 187 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 417 + source 187 + target 357 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 418 + source 187 + target 490 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 419 + source 188 + target 280 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 420 + source 188 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 421 + source 188 + target 470 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 422 + source 188 + target 491 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 423 + source 188 + target 492 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 424 + source 189 + target 239 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 425 + source 189 + target 334 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 426 + source 190 + target 266 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 427 + source 191 + target 493 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 428 + source 192 + target 470 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 429 + source 193 + target 198 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 430 + source 193 + target 440 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 431 + source 194 + target 494 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 432 + source 194 + target 495 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 433 + source 195 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 434 + source 196 + target 259 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 435 + source 197 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 436 + source 198 + target 359 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 437 + source 198 + target 496 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 438 + source 199 + target 352 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 439 + source 200 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 440 + source 201 + target 243 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 441 + source 202 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 442 + source 202 + target 497 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 443 + source 202 + target 498 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 444 + source 203 + target 278 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 445 + source 204 + target 216 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 446 + source 204 + target 259 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 447 + source 204 + target 499 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 448 + source 204 + target 500 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 449 + source 205 + target 492 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 450 + source 206 + target 458 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 451 + source 206 + target 476 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 452 + source 206 + target 501 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 453 + source 207 + target 278 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 454 + source 208 + target 470 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 455 + source 209 + target 502 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 456 + source 210 + target 503 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 457 + source 211 + target 296 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 458 + source 211 + target 403 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 459 + source 211 + target 504 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 460 + source 212 + target 355 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 461 + source 213 + target 280 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 462 + source 214 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 463 + source 215 + target 429 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 464 + source 215 + target 505 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 465 + source 216 + target 506 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 466 + source 217 + target 231 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 467 + source 217 + target 245 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 468 + source 217 + target 507 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 469 + source 218 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 470 + source 219 + target 243 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 471 + source 219 + target 276 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 472 + source 220 + target 258 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 473 + source 220 + target 306 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 474 + source 220 + target 508 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 475 + source 220 + target 509 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 476 + source 221 + target 276 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 477 + source 221 + target 510 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 478 + source 221 + target 511 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 479 + source 222 + target 502 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 480 + source 222 + target 512 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 481 + source 223 + target 265 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 482 + source 224 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 483 + source 225 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 484 + source 225 + target 513 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 485 + source 226 + target 266 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 486 + source 226 + target 514 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 487 + source 227 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 488 + source 227 + target 437 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 489 + source 228 + target 265 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 490 + source 229 + target 258 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 491 + source 229 + target 278 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 492 + source 229 + target 515 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 493 + source 230 + target 293 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 494 + source 231 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 495 + source 232 + target 516 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 496 + source 233 + target 516 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 497 + source 234 + target 361 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 498 + source 235 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 499 + source 235 + target 517 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 500 + source 236 + target 495 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 501 + source 237 + target 518 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 502 + source 238 + target 502 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 503 + source 239 + target 267 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 504 + source 239 + target 339 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 505 + source 239 + target 340 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 506 + source 239 + target 341 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 507 + source 239 + target 349 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 508 + source 239 + target 449 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 509 + source 239 + target 519 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 510 + source 240 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 511 + source 241 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 512 + source 242 + target 496 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 513 + source 242 + target 520 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 514 + source 242 + target 521 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 515 + source 243 + target 402 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 516 + source 243 + target 522 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 517 + source 244 + target 354 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 518 + source 245 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 519 + source 246 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 520 + source 247 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 521 + source 247 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 522 + source 247 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 523 + source 247 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 524 + source 248 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 525 + source 249 + target 315 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 526 + source 250 + target 397 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 527 + source 251 + target 266 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 528 + source 252 + target 523 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 529 + source 253 + target 307 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 530 + source 253 + target 524 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 531 + source 254 + target 308 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 532 + source 255 + target 525 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 533 + source 256 + target 344 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 534 + source 257 + target 318 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 535 + source 258 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 536 + source 258 + target 526 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 537 + source 258 + target 527 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 538 + source 258 + target 528 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 539 + source 259 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 540 + source 259 + target 397 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 541 + source 259 + target 529 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 542 + source 260 + target 311 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 543 + source 261 + target 405 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 544 + source 262 + target 301 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 545 + source 262 + target 392 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 546 + source 262 + target 530 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 547 + source 263 + target 265 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 548 + source 264 + target 289 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 549 + source 265 + target 429 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 550 + source 265 + target 531 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 551 + source 265 + target 532 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 552 + source 265 + target 533 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 553 + source 266 + target 344 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 554 + source 266 + target 534 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 555 + source 267 + target 340 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 556 + source 268 + target 425 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 557 + source 269 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 558 + source 269 + target 535 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 559 + source 270 + target 294 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 560 + source 270 + target 536 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 561 + source 271 + target 461 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 562 + source 271 + target 537 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 563 + source 272 + target 361 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 564 + source 273 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 565 + source 274 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 566 + source 274 + target 403 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 567 + source 275 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 568 + source 276 + target 334 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 569 + source 277 + target 431 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 570 + source 278 + target 287 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 571 + source 278 + target 538 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 572 + source 278 + target 539 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 573 + source 278 + target 540 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 574 + source 279 + target 429 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 575 + source 279 + target 514 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 576 + source 280 + target 284 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 577 + source 281 + target 306 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 578 + source 282 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 579 + source 283 + target 448 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 580 + source 284 + target 393 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 581 + source 284 + target 425 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 582 + source 284 + target 431 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 583 + source 284 + target 437 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 584 + source 284 + target 442 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 585 + source 284 + target 459 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 586 + source 284 + target 541 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 587 + source 285 + target 542 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 588 + source 286 + target 543 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 589 + source 287 + target 302 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 590 + source 288 + target 310 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 591 + source 289 + target 423 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 592 + source 290 + target 291 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 593 + source 290 + target 459 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 594 + source 291 + target 305 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 595 + source 292 + target 437 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 596 + source 293 + target 448 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 597 + source 294 + target 356 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 598 + source 295 + target 311 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 599 + source 296 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 600 + source 297 + target 527 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 601 + source 298 + target 312 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 602 + source 299 + target 361 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 603 + source 300 + target 544 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 604 + source 301 + target 311 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 605 + source 302 + target 409 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 606 + source 302 + target 431 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 607 + source 302 + target 541 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 608 + source 303 + target 306 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 609 + source 303 + target 545 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 610 + source 303 + target 546 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 611 + source 304 + target 397 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 612 + source 305 + target 459 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 613 + source 306 + target 509 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 614 + source 307 + target 461 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 615 + source 307 + target 470 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 616 + source 308 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 617 + source 308 + target 447 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 618 + source 308 + target 547 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 619 + source 308 + target 548 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 620 + source 309 + target 340 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 621 + source 310 + target 352 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 622 + source 311 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 623 + source 312 + target 549 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 624 + source 312 + target 550 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 625 + source 312 + target 551 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 626 + source 312 + target 552 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 627 + source 313 + target 327 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 628 + source 314 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 629 + source 314 + target 326 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 630 + source 314 + target 403 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 631 + source 314 + target 553 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 632 + source 315 + target 325 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 633 + source 316 + target 397 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 634 + source 317 + target 352 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 635 + source 318 + target 492 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 636 + source 318 + target 554 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 637 + source 319 + target 425 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 638 + source 320 + target 335 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 639 + source 321 + target 555 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 640 + source 321 + target 556 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 641 + source 322 + target 425 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 642 + source 323 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 643 + source 324 + target 467 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 644 + source 325 + target 327 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 645 + source 326 + target 557 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] + edge [ + id 646 + source 327 + target 558 + pajek [ + dir 0.0 + weight 1.0 + ] + graphics [ + fill "#000000" + outline "#000000" + frameThickness 1.0 + rounding 5.0 + gradient 0.0 + arrow "none" + thickness 1.0 + ] + ] +] diff --git a/src/3rdparty/adaptagrams/libcola/tests/gml_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/gml_graph.cpp new file mode 100644 index 0000000..6a280cf --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/gml_graph.cpp @@ -0,0 +1,257 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <fstream> +#include <iostream> +#include <string> +#include <sstream> +#include <boost/regex.hpp> +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; + +typedef map<unsigned,unsigned> NodeIdMap; +typedef map<string,list<unsigned> > Partitions; + +Edge readEdge(ifstream &f) { + string l; + int indent=1; + unsigned source, target; + boost::regex sourceRE(".*source\\s+(\\d+).*"); + boost::regex targetRE(".*target\\s+(\\d+).*"); + boost::smatch matches; + while(!getline(f,l).eof()) { + if(boost::regex_match(l,matches,sourceRE)) { + std::istringstream i(matches[1]); + i>>source; + } + if(boost::regex_match(l,matches,targetRE)) { + std::istringstream i(matches[1]); + i>>target; + } + if(l.find("[")!=string::npos) { + indent++; + } + if(l.find("]")!=string::npos) { + indent--; + if(indent==0) { + return make_pair(source,target); + } + } + } + cerr << "Incomplete edge definition!" << endl; + return make_pair(0,0); +} + +unsigned readNode(ifstream &f, NodeIdMap &nodeIdMap, + Partitions &partitions) { + static unsigned nodeCtr=0; + int indent=1; + string l; + boost::regex idRE("\\s*id\\s+(\\d+).*"); + boost::regex fillRE(".*fill\\s+\"#(.+)\".*"); + boost::smatch matches; + unsigned id; + while(!getline(f,l).eof()) { + if(boost::regex_match(l,matches,idRE)) { + std::istringstream i(matches[1]); + i>>id; + nodeIdMap[id]=nodeCtr++; + } + if(boost::regex_match(l,matches,fillRE)) { + string partition(matches[1]); + Partitions::iterator i=partitions.find(partition); + partitions[partition].push_back(nodeIdMap[id]); + } + if(l.find("[")!=string::npos) { + indent++; + } + if(l.find("]")!=string::npos) { + indent--; + if(indent==0) { + return nodeCtr; + } + } + } + cerr << "Incomplete node definition!" << endl; + return 0; +} + +struct PostIteration : TestConvergence { + PostIteration(vector<vpsc::Rectangle*> &rs, vector<list<unsigned> > &ps, vector<double> &bs, const double d,const unsigned i) : TestConvergence(d,i), rs(rs), ps(ps), bs(bs) {} + bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) { + static int iterations=0; + unsigned n=X.size(); + double centreX=0,centreY=0; + for(unsigned i=0;i<n;i++) { + centreX+=X[i]; + centreY+=Y[i]; + } + centreX/=(double)n; + centreY/=(double)n; + //printf("centre=(%f,%f)\n",centreX,centreY); + for(unsigned i=0;i<ps.size();i++) { + for(list<unsigned>::iterator v=ps[i].begin();v!=ps[i].end();v++) { + double dx=X[*v]-centreX, dy=Y[*v]-centreY; + double l=sqrt(dx*dx+dy*dy); + if(i>0) { + double r=bs[i-1]+10; + if(l<r) { + double dx1=dx*(r/l), dy1=dy*(r/l); + X[*v]=centreX+dx1; + Y[*v]=centreY+dy1; + } + } + if(i<ps.size()-1) { + double r=bs[i]-10; + if(l>r) { + double dx1=dx*(r/l), dy1=dy*(r/l); + X[*v]=centreX+dx1; + Y[*v]=centreY+dy1; + } + } + } + } + for(unsigned i=0;i<rs.size();i++) { + rs[i]->moveCentre(X[i],Y[i]); + } + cout << iterations++ << ":stress="<<new_stress<<endl; + return TestConvergence::operator()(new_stress,X,Y); + } + vector<vpsc::Rectangle*> &rs; + vector<list<unsigned> > &ps; + vector<double> &bs; +}; +int main() { + //const char *fname="data/test.gml"; + string fname("data/uetzNetworkGSC-all.gml"); + ifstream f(fname.c_str()); + if(!f.is_open()) { + cout << "Error opening file: " << fname << endl; + exit(1); + } + unsigned V = 0; + double defaultEdgeLength=40; + vector<Edge> es; + CompoundConstraints cx,cy; + NodeIdMap nodeIdMap; + Partitions partitions; + string l; + boost::regex nodeRE(".*node\\s+\\[.*"); + boost::regex edgeRE(".*edge\\s+\\[.*"); + while(!getline(f,l).eof()) { + if(boost::regex_match(l,nodeRE)) { + V=readNode(f,nodeIdMap,partitions); + } + if(boost::regex_match(l,edgeRE)) { + pair<unsigned,unsigned> e=readEdge(f); + unsigned start=nodeIdMap[e.first]; + unsigned end=nodeIdMap[e.second]; + //printf("edge (%d,%d)\n",start,end); + es.push_back(make_pair(start,end)); + //cy.push_back( + //new SeparationConstraint(start,end,defaultEdgeLength/3)); + } + } + assert(V==nodeIdMap.size()); + /* + unsigned p1=V++; + unsigned p2=V++; + // red at the top + list<unsigned> &p=partitions[string("FF3333")]; + //double cgap=defaultEdgeLength/3; + double cgap=0; + for(list<unsigned>::iterator j=p.begin();j!=p.end();j++) { + cy.push_back( + new SeparationConstraint(*j,p1,cgap)); + } + // yellow in the middle + p=partitions[string("FFFF00")]; + for(list<unsigned>::iterator j=p.begin();j!=p.end();j++) { + cy.push_back( + new SeparationConstraint(p1,*j,cgap)); + cy.push_back( + new SeparationConstraint(*j,p2,cgap)); + } + // green at the bottom + p=partitions[string("00FF00")]; + for(list<unsigned>::iterator j=p.begin();j!=p.end();j++) { + cy.push_back( + new SeparationConstraint(p2,*j,cgap)); + } + */ + cout << "V="<<V<<endl; + double width=1000; + double height=1000; + vector<vpsc::Rectangle*> rs; + cout << "|V|=" << V << endl; + //srand(time(nullptr)); + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+1,y,y+1)); + } + vector<list<unsigned> > ps; + ps.push_back(partitions[string("FF3333")]); + ps.push_back(partitions[string("FFFF00")]); + ps.push_back(partitions[string("00FF00")]); + vector<double> bs; + bs.push_back(80); + bs.push_back(120); + PostIteration test(rs,ps,bs,0.0001,200); + ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test); + //ConstrainedFDLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test); + //alg.setConstrainedLayout(true); + //alg.setScaling(true); + //alg.setXConstraints(&cx); + //alg.setYConstraints(&cy); + alg.run(); + /* + vector<ColourRGBA> colours(V); + list<unsigned> &p=partitions[string("FF3333")]; + for(list<unsigned>::iterator i=p.begin();i!=p.end();i++) { + //colours[*i]=ColourRGBA(1.,0,0.3,1.); + colours[*i]=ColourRGBA(0,0,0,1.); + } + p=partitions[string("FFFF00")]; + for(list<unsigned>::iterator i=p.begin();i!=p.end();i++) { + //colours[*i]=ColourRGBA((unsigned)255,162,99,255); + colours[*i]=ColourRGBA(0,0,0,1.); + } + p=partitions[string("00FF00")]; + for(list<unsigned>::iterator i=p.begin();i!=p.end();i++) { + //colours[*i]=ColourRGBA((unsigned)24,157,0,255); + colours[*i]=ColourRGBA(0,0,0,1.); + } + */ + OutputFile of(rs,es,nullptr,"gml_graph-constrained.svg",false,true); + //of.colours=&colours; + of.generate(); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/graphlayouttest.h b/src/3rdparty/adaptagrams/libcola/tests/graphlayouttest.h new file mode 100644 index 0000000..2cc51e7 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/graphlayouttest.h @@ -0,0 +1,275 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <sstream> +#include <ctime> + +#include <libvpsc/rectangle.h> +#include <libcola/cola.h> +#include <libtopology/topology_graph.h> +#include <libcola/output_svg.h> + +inline double getRand(double range) { + return range*rand()/RAND_MAX; +} + +namespace DFS { +using namespace std; +using namespace cola; +struct Node { + unsigned id; + bool visited; + typedef vector<Node*> PNodes; + PNodes neighbours; + void visit(vector<unsigned> &order) { + visited=true; + unsigned mid=neighbours.size()/2; + for(unsigned i=0;i<mid;i++) { + if(!neighbours[i]->visited) { + neighbours[i]->visit(order); + } + } + order.push_back(id); + for(unsigned i=mid;i<neighbours.size();i++) { + if(!neighbours[i]->visited) { + neighbours[i]->visit(order); + } + } + } + void visit_leaves(vector<unsigned> &order) { + unsigned mid=neighbours.size()/2; + Node *v; + for(unsigned i=0;i<mid;i++) { + v=neighbours[i]; + if(v->neighbours.size()==0) { + order.push_back(v->id); + } + } + order.push_back(id); + for(unsigned i=mid;i<neighbours.size();i++) { + v=neighbours[i]; + if(v->neighbours.size()==0) { + order.push_back(v->id); + } + } + } +}; + +struct Graph { + typedef vector<Edge> Edges; + typedef vector<Node> Nodes; + Nodes nodes; + vector<unsigned> order; + vector<vector<unsigned> > leaves; + Graph(unsigned n,vector<Edge> &edges) { + nodes.resize(n); + order.resize(0); + leaves.resize(n); + for(Edges::iterator i=edges.begin();i!=edges.end();i++) { + nodes[i->first].neighbours.push_back(&nodes[i->second]); + } + for(unsigned i=0;i<nodes.size();i++) { + nodes[i].id=i; + nodes[i].visited=false; + } + for(Nodes::iterator i=nodes.begin();i!=nodes.end();i++) { + if(!i->visited) { + i->visit(order); + } + } + for(unsigned i=0;i<nodes.size();i++) { + leaves[i].resize(0); + nodes[i].visit_leaves(leaves[i]); + } + assert(order.size()==nodes.size()); + } +}; +} // namespace DFS +using namespace cola; +using namespace std; +struct CheckProgress : TestConvergence { + CheckProgress(const double d,const unsigned i) : TestConvergence(d,i) {} + bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) { + cout << "stress="<<new_stress<<" iteration="<<iterations<<endl; + return TestConvergence::operator()(new_stress,X,Y); + } +}; + +enum SolverType { CG, UGP, SGP, IP }; +void run_test( + vector<pair<double,double> > const &startpos, + vector<Edge> const &es, + const double defaultEdgeLength, + CompoundConstraints &ccs, + const SolverType s, + const bool constrained, + const char *fname, + const char *testdesc) { + vector<vpsc::Rectangle*> rs; + unsigned V=startpos.size(); + cout << "|V|=" << V << endl; + //srand(time(nullptr)); + for(unsigned i=0;i<V;i++) { + double x=startpos[i].first, y=startpos[i].second; + rs.push_back(new vpsc::Rectangle(x,x+1,y,y+1)); + } + CheckProgress test(0.001,100); + clock_t starttime=clock(); + ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength, + StandardEdgeLengths,&test); + switch(s) { + cout << "Solver: "; + case SGP: + cout << "Scaled GP" << endl; + alg.setConstrainedLayout(true); + alg.setScaling(true); + break; + case UGP: + cout << "Unscaled GP" << endl; + alg.setConstrainedLayout(true); + alg.setScaling(false); + break; + case CG: + cout << "Conjugate Gradient" << endl; + alg.setConstrainedLayout(false); + break; + case IP: + cout << "Interior Point" << endl; + alg.setExternalSolver(true); + alg.setConstrainedLayout(true); + break; + } + if(!constrained) { + cout << "Unconstrained layout" << endl; + } else { + cout << "Constrained layout" << endl; + printf("|CompoundConstraints|=%u\n",(unsigned)ccs.size()); + alg.setConstraints(&ccs); + } + alg.run(); + double t=double(clock()-starttime)/double(CLOCKS_PER_SEC); + ostringstream ss; + ss << fname << "_" << V << "_" << testdesc << ".svg"; + + cout<<ss.str()<<" Time="<<t<<endl; + OutputFile of(rs,es,nullptr,ss.str().c_str(),false,true); + of.generate(); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } +} +void writeFile(const topology::Nodes& vs, const topology::Edges& es, const string& outputFileName) { + const unsigned n=vs.size(); + vector<cola::Edge> cedges; + + for(unsigned i=0;i<es.size();i++) { + cedges.push_back(make_pair(1,2)); + } + + vector<straightener::Route*> routes; + for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) { + routes.push_back((*e)->getRoute()); + } + + vector<string> labels(n); + for(unsigned i=0;i<n;++i) { + stringstream ss; + ss << i; + labels[i]=ss.str(); + } + + vector<vpsc::Rectangle*> rs; + for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) { + rs.push_back((*i)->rect); + } + OutputFile of(rs,cedges,nullptr,outputFileName,true,false); + of.setLabels(labels); + of.routes=&routes; + of.generate(); + + for_each(routes.begin(),routes.end(),delete_object()); +} + +void writeDunnartFile(const topology::Nodes& vs, const vector<std::pair<unsigned int, unsigned int> >& es, const string& outputFileName) { + FILE *fp = fopen(outputFileName.c_str(), "w"); + assert (fp != nullptr); + + fprintf(fp, "<svg xmlns:dunnart=\"http://www.csse.monash.edu.au/~mwybrow/dunnart.dtd\">\n"); + for(unsigned int i = 0; i < vs.size(); ++i) { + vpsc::Rectangle *rect = vs[i]->rect; + + int id = i + 1; + fprintf(fp, "<rect id=\"%d\" dunnart:label=\"\" dunnart:width=\"20\" " + "dunnart:height=\"20\" dunnart:xPos=\"%f\" " + "dunnart:yPos=\"%f\" dunnart:type=\"rect\" />\n", id, + rect->getCentreX(), rect->getCentreY()); + } + + for(unsigned int i = 0; i < es.size(); ++i) { + const std::pair<unsigned int, unsigned int>& edge = es[i]; + + int id = i + 1 + vs.size(); + fprintf(fp, "<path id=\"%d\" dunnart:srcID=\"%d\" " + "dunnart:srcFlags=\"544\" dunnart:dstID=\"%d\" " + "dunnart:dstFlags=\"544\" dunnart:directed=\"1\" " + "dunnart:type=\"connAvoidPoly\" />\n", id, + edge.first + 1, edge.second + 1); + } + + fprintf(fp, "</svg>\n"); + + fclose(fp); + +#if 0 + for(unsigned i=0;i<es.size();i++) { + cedges.push_back(make_pair(1,2)); + } + + vector<straightener::Route*> routes; + for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) { + routes.push_back((*e)->getRoute()); + } + + vector<string> labels(n); + for(unsigned i=0;i<n;++i) { + stringstream ss; + ss << i; + labels[i]=ss.str(); + } + + vector<vpsc::Rectangle*> rs; + for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) { + rs.push_back((*i)->rect); + } + OutputFile of(rs,cedges,nullptr,outputFileName,true,false); + of.setLabels(labels); + of.routes=&routes; + of.generate(); + + for_each(routes.begin(),routes.end(),delete_object()); +#endif +} + +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4: diff --git a/src/3rdparty/adaptagrams/libcola/tests/initialOverlap.cpp b/src/3rdparty/adaptagrams/libcola/tests/initialOverlap.cpp new file mode 100644 index 0000000..4f0a8bf --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/initialOverlap.cpp @@ -0,0 +1,168 @@ +// Check that rectangles that start at same position don't get stuck on top of each other +// during force-directed layout. +#include <vector> +#include <utility> +#include "libcola/cola.h" +#include "libcola/pseudorandom.h" + +using namespace cola; + +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + EdgeLengths eLengths; + double defaultEdgeLength=1; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 20, 0, 20); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 20, 0, 20); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 20, 0, 20); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 20, 0, 20); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 20, 0, 20); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 60, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + rect = new vpsc::Rectangle(0, 100, 0, 60); + rs.push_back(rect); + + es.push_back(std::make_pair(0, 3)); + es.push_back(std::make_pair(1, 3)); + es.push_back(std::make_pair(2, 3)); + es.push_back(std::make_pair(2, 8)); + es.push_back(std::make_pair(2, 11)); + es.push_back(std::make_pair(3, 4)); + es.push_back(std::make_pair(3, 5)); + es.push_back(std::make_pair(6, 8)); + es.push_back(std::make_pair(7, 8)); + es.push_back(std::make_pair(8, 22)); + es.push_back(std::make_pair(8, 23)); + es.push_back(std::make_pair(9, 11)); + es.push_back(std::make_pair(10, 11)); + es.push_back(std::make_pair(11, 12)); + es.push_back(std::make_pair(11, 23)); + es.push_back(std::make_pair(12, 13)); + es.push_back(std::make_pair(12, 14)); + es.push_back(std::make_pair(13, 17)); + es.push_back(std::make_pair(13, 18)); + es.push_back(std::make_pair(13, 19)); + es.push_back(std::make_pair(13, 20)); + es.push_back(std::make_pair(14, 15)); + es.push_back(std::make_pair(14, 16)); + es.push_back(std::make_pair(14, 20)); + es.push_back(std::make_pair(14, 21)); + + eLengths.resize(25); + eLengths[0] = 100; + eLengths[1] = 100; + eLengths[2] = 100; + eLengths[3] = 100; + eLengths[4] = 100; + eLengths[5] = 100; + eLengths[6] = 100; + eLengths[7] = 100; + eLengths[8] = 100; + eLengths[9] = 100; + eLengths[10] = 100; + eLengths[11] = 100; + eLengths[12] = 100; + eLengths[13] = 100; + eLengths[14] = 100; + eLengths[15] = 100; + eLengths[16] = 100; + eLengths[17] = 100; + eLengths[18] = 100; + eLengths[19] = 100; + eLengths[20] = 100; + eLengths[21] = 100; + eLengths[22] = 100; + eLengths[23] = 100; + eLengths[24] = 100; + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths); + alg.run(); + //alg.outputInstanceToSVG("initialOverlap"); + + bool overlaps = false; + + for (size_t i = 0; i < rs.size(); ++i) + { + for (size_t j = i + 1; j < rs.size(); ++j) + { + overlaps |= ((rs[i]->overlapD(0, rs[j]) > 0) && (rs[i]->overlapD(1, rs[j]) > 0)); + if (overlaps) + { + break; + } + } + if (overlaps) + { + break; + } + } + + alg.freeAssociatedObjects(); + + return (overlaps) ? 1 : 0; +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/invalid.cpp b/src/3rdparty/adaptagrams/libcola/tests/invalid.cpp new file mode 100644 index 0000000..175a6b7 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/invalid.cpp @@ -0,0 +1,80 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + + +/** \file + * Interface between Inkscape code (SPItem) and graphlayout functions. + * + * Authors: + * Tim Dwyer <tgdwyer@gmail.com> + */ +#include <iostream> + +#include <vector> +#include <algorithm> +#include <float.h> +#include <libcola/cola.h> +//#include <libvspc/exceptions.h> +#include <libvpsc/constraint.h> +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; +int main() { + + const unsigned V = 2; + typedef pair < unsigned, unsigned >Edge; + Edge edge_array[] = { Edge(0, 1) }; + unsigned E = sizeof(edge_array) / sizeof(Edge); + vector<Edge> es(edge_array,edge_array+E); + double width=100; + double height=100; + vector<vpsc::Rectangle*> rs; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5)); + } + ConstrainedFDLayout alg(rs, es, width/2); + CompoundConstraints ccs; + AlignmentConstraint ac(vpsc::YDIM); + ccs.push_back(&ac); + ac.addShape(0,0); + ac.addShape(5,0); + alg.setConstraints(ccs); + try { + alg.run(); + } catch (cola::InvalidVariableIndexException& e) { + cerr << e.what() << endl; + return 0; + } + //assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001); + cout<<rs[0]->getCentreX()<<","<<rs[1]->getCentreX()<<endl; + //output_svg(rs,es,"unsatisfiable.svg"); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 1; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/large_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/large_graph.cpp new file mode 100644 index 0000000..a236991 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/large_graph.cpp @@ -0,0 +1,144 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +// Loads a graph from a text file, generates constraints for each edge requiring them +// to point downwards, and proceeds to produce a layout using libcola. +// The input file format is 2 numeric node labels per line separated by a space, +// each pair representing a directed edge. Node labels are simply used as array +// offsets so they should start from 0. +// The graph should be connected. +// Default input file is the matrix market 1138_bus graph. +// Running times: +// no constraints - steepest descent solver: 149 seconds +// no constraints - mosek: 49.47 seconds +// no constraints - conjugate gradient solver: 12.2 seconds +// dir-edge constraints - mosek: 214.2 seconds +// +// V=1138 +#include<iostream> +#include<iomanip> +#include<fstream> +#include<vector> +#include<valarray> +#include <libvpsc/linesegment.h> +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; + +int countCrossings(vpsc::Rectangles& rs, vector<cola::Edge>& es) { + int crossings=0; + for(unsigned i=0;i<es.size()-1;++i) { + for(unsigned j=i+1;j<es.size();++j) { + Edge e1=es[i], e2=es[j]; + Rectangle *e1a=rs[e1.first], + *e1b=rs[e1.second], + *e2a=rs[e2.first], + *e2b=rs[e2.second]; + linesegment::LineSegment s1( + linesegment::Vector(e1a->getCentreX(),e1a->getCentreY()), + linesegment::Vector(e1b->getCentreX(),e1b->getCentreY())); + linesegment::LineSegment s2( + linesegment::Vector(e2a->getCentreX(),e2a->getCentreY()), + linesegment::Vector(e2b->getCentreX(),e2b->getCentreY())); + linesegment::Vector point; + if(s1.Intersect(s2,point)==linesegment::LineSegment::INTERSECTING) { + ++crossings; + } + } + } + return crossings; +} +int main() { + const char *fname="data/1138_bus.txt"; //"data/dg_850.txt"; + ifstream f(fname); + if(!f.is_open()) { + cout << "Error opening file: " << fname << endl; + exit(1); + } + string startlabel, endlabel; + unsigned V = 0; + double defaultEdgeLength=40; + vector<Edge> es; + CompoundConstraints cx,cy; + while(!getline(f,startlabel,' ').eof()) { + getline(f,endlabel); + unsigned start = atoi(startlabel.c_str()), + end = atoi(endlabel.c_str()); + es.push_back(make_pair(start,end)); + cy.push_back( + new SeparationConstraint(end,start,defaultEdgeLength/3)); + V=max(V,max(start,end)); + } + V++; + /* + DFS::Graph dfs(V,es); + for(unsigned i=1;i<dfs.order.size();i++) { + cx.push_back( + new SeparationConstraint(dfs.order[i-1],dfs.order[i],0)); + } + */ + cout << "V="<<V<<endl; + double width=1000; + double height=1000; + vector<pair<double,double> > startpos(V); + //srand(time(nullptr)); + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + startpos[i]=make_pair(x,y); + } + //const char *testname="large_graph"; + //run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,testname,"cg"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,testname,"ip"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,testname,"ugp"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,testname,"sgp"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,testname,"cip"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,testname,"cugp"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,testname,"csgp"); + vector<vpsc::Rectangle*> rs; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5)); + } + cout<<"Initial crossings="<<countCrossings(rs,es)<<endl; + CheckProgress test(0.0001,200); + ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test); + alg.setYConstraints(&cy); + alg.run(); + cout<<"Majorization crossings="<<countCrossings(rs,es)<<endl; + OutputFile output1(rs,es,nullptr,"large_graph-majorization.pdf"); + output1.generate(); + ConstrainedFDLayout alg2(rs,es,defaultEdgeLength,nullptr,test); + alg2.setYConstraints(&cy); + alg2.run(); + cout<<"PStress crossings="<<countCrossings(rs,es)<<endl; + OutputFile output(rs,es,nullptr,"large_graph.pdf"); + output.generate(); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/makefeasible.cpp b/src/3rdparty/adaptagrams/libcola/tests/makefeasible.cpp new file mode 100644 index 0000000..4bfb082 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/makefeasible.cpp @@ -0,0 +1,368 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <iostream> +#include <vector> +#include <cmath> +#include <time.h> +#include <valarray> +#include <fstream> +#include <sstream> + +#include <libavoid/libavoid.h> +#include <libavoid/router.h> + +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; +using namespace vpsc; + +/* +// |V|=12, |E|=23 +static const unsigned DAGDEPTH = 3; +static const unsigned BRANCHFACTOR = 3; +static const double EXTRAEDGEPROB = 0.5; +*/ +/* +// |V|=26, |E|=61 +static const unsigned DAGDEPTH = 3; +static const unsigned BRANCHFACTOR = 4; +static const double EXTRAEDGEPROB = 0.1; +*/ + +/* +// |V|=62, |E|=85 +static const unsigned DAGDEPTH = 4; +static const unsigned BRANCHFACTOR = 4; +static const double EXTRAEDGEPROB = 0.01; +*/ +/* +// |V|=131, |E|=166 +static const unsigned DAGDEPTH = 5; +static const unsigned BRANCHFACTOR = 4; +static const double EXTRAEDGEPROB = 0.005; +*/ + +static const unsigned DAGDEPTH = 6; +static const unsigned BRANCHFACTOR = 4; +static const double EXTRAEDGEPROB = 0.002; +/* +// |V|=343, |E|=487 +seed=1208390913; +static const unsigned DAGDEPTH = 6; +static const unsigned BRANCHFACTOR = 4; +static const double EXTRAEDGEPROB = 0.002; +*/ + +void makeEdge(unsigned u, unsigned v, + vector<Edge> &edges, CompoundConstraints &ccs) { + edges.push_back(make_pair(u,v)); + ccs.push_back(new SeparationConstraint(vpsc::YDIM, u,v,5)); +} +vector<Edge> random_dag(unsigned depth, unsigned maxbranch, unsigned &V, + CompoundConstraints &ccs) { + printf("DAG depth=%d\nmaxbranch=%d\nextraedgeprob%f\n",depth,maxbranch,EXTRAEDGEPROB); + vector<Edge> edges; + unsigned lstart=0, lend=1; + V=0; + for(unsigned i=0;i<depth;i++) { + for(unsigned j=lstart;j<lend;j++) { + //makeEdge(j,++V,edges,cy); + //makeEdge(j,++V,edges,cy); + for(unsigned k=0;k<maxbranch;k++) { + double r=(double)rand()/(double)RAND_MAX; + if(r < 0.5) { + makeEdge(j,++V,edges,ccs); + } + } + } + lstart=lend; + lend=V+1; + } + V++; + /* + DFS::Graph dfs(V,edges); + for(unsigned i=1;i<dfs.order.size();i++) { + cx.push_back( + new SeparationConstraint(dfs.order[i-1],dfs.order[i],0.5)); + } + */ + for(unsigned i=0;i<V;++i) { + for(unsigned j=i+1;j<V;++j) { + double r=(double)rand()/(double)RAND_MAX; + if(r < EXTRAEDGEPROB) { + makeEdge(i,j,edges,ccs); + } + } + } + /* + for(unsigned i=0;i<dfs.leaves.size();i++) { + for(unsigned j=1;j<dfs.leaves[i].size();j++) { + cx.push_back( new SeparationConstraint(dfs.leaves[i][j-1],dfs.leaves[i][j],10)); + } + } + */ + return edges; +} +void removeoverlaps(vpsc::Rectangles &rs, bool bothaxes) { + double xBorder=0, yBorder=0; + static const double EXTRA_GAP=1e-5; + unsigned n=rs.size(); + try { + // The extra gap avoids numerical imprecision problems + Rectangle::setXBorder(xBorder+EXTRA_GAP); + Rectangle::setYBorder(yBorder+EXTRA_GAP); + vpsc::Variables vs(n); + unsigned i=0; + for(Variables::iterator v=vs.begin();v!=vs.end();++v,++i) { + *v=new Variable(i,0,1); + } + vpsc::Constraints cs; + vpsc::generateXConstraints(rs,vs,cs,bothaxes); + vpsc::IncSolver vpsc_x(vs,cs); + vpsc_x.solve(); + vpsc::Rectangles::iterator r=rs.begin(); + for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) { + assert((*v)->finalPosition==(*v)->finalPosition); + (*r)->moveCentreX((*v)->finalPosition); + } + assert(r==rs.end()); + for_each(cs.begin(),cs.end(),vpsc::delete_object()); + cs.clear(); + if(bothaxes) { + // Removing the extra gap here ensures things that were moved to be adjacent to one another above are not considered overlapping + Rectangle::setXBorder(Rectangle::xBorder-EXTRA_GAP); + vpsc::generateYConstraints(rs,vs,cs); + vpsc::IncSolver vpsc_y(vs,cs); + vpsc_y.solve(); + r=rs.begin(); + for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) { + (*r)->moveCentreY((*v)->finalPosition); + } + for_each(cs.begin(),cs.end(),vpsc::delete_object()); + cs.clear(); + Rectangle::setYBorder(Rectangle::yBorder-EXTRA_GAP); + vpsc::generateXConstraints(rs,vs,cs,false); + vpsc::IncSolver vpsc_x2(vs,cs); + vpsc_x2.solve(); + r=rs.begin(); + for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) { + (*r)->moveCentreX((*v)->finalPosition); + } + for_each(cs.begin(),cs.end(),vpsc::delete_object()); + } + for_each(vs.begin(),vs.end(),vpsc::delete_object()); + } catch (char *str) { + std::cerr<<str<<std::endl; + for(vpsc::Rectangles::iterator r=rs.begin();r!=rs.end();++r) { + std::cerr << **r <<std::endl; + } + } + Rectangle::setXBorder(xBorder); + Rectangle::setYBorder(yBorder); +} +/* +void writeTextFile(vector<cola::Edge>& edges) { + ofstream outfile("new.txt",ofstream::binary); + for(vector<cola::Edge>::iterator e=edges.begin();e!=edges.end();++e) { + outfile<<"node"<<e->first<<",node"<<e->second<<endl; + } + outfile.close(); +} +*/ +/* + * Make feasible: + * - remove overlaps between rectangular boundaries of nodes/clusters + * (respecting structural constraints) + * - perform routing (preserve previous topology using rubber banding) + */ +void makeFeasible(vpsc::Rectangles& rs, vector<cola::Edge>& edges, + std::vector<topology::Edge*>& routes, + std::vector<topology::Node*>& topologyNodes, double defaultEdgeLength) { + printf("Removing overlaps...\n"); + removeoverlaps(rs,false); + printf("done.\n"); + printf("Running libavoid to compute routes...\n"); + clock_t libavoidstarttime=clock(); + // find feasible routes for edges + Avoid::Router *router = new Avoid::Router(Avoid::PolyLineRouting); + // Use rotational sweep for point visibility + router->UseLeesAlgorithm = true; + // Don't use invisibility graph. + router->InvisibilityGrph = false; + double g=0; // make shape that libavoid sees slightly smaller + for(unsigned i=0;i<rs.size();++i) { + vpsc::Rectangle* r=rs[i]; + double x=r->getMinX()+g; + double X=r->getMaxX()-g; + double y=r->getMinY()+g; + double Y=r->getMaxY()-g; + // Create the ShapeRef: + Avoid::Polygon shapePoly(4); + // AntiClockwise! + shapePoly.ps[0] = Avoid::Point(X,y); + shapePoly.ps[1] = Avoid::Point(X,Y); + shapePoly.ps[2] = Avoid::Point(x,Y); + shapePoly.ps[3] = Avoid::Point(x,y); + //if(i==4||i==13||i==9) { + //printf("rect[%d]:{%f,%f,%f,%f}\n",i,x,y,X,Y); + //} + unsigned int shapeID = i + 1; + Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly, + shapeID); + // ShapeRef constructor makes a copy of polygon so we can free it: + router->addShape(shapeRef); + } + for(unsigned i=0;i<edges.size();++i) { + cola::Edge e=edges[i]; + Avoid::ConnRef *connRef; + unsigned int connID = i + rs.size() + 1; + Rectangle* r0=rs[e.first], *r1=rs[e.second]; + Avoid::Point srcPt(r0->getCentreX(),r0->getCentreY()); + Avoid::Point dstPt(r1->getCentreX(),r1->getCentreY()); + connRef = new Avoid::ConnRef(router, srcPt, dstPt, connID); + router->processTransaction(); + const Avoid::Polygon& route = connRef->route(); + vector<topology::EdgePoint*> eps; + eps.push_back( new topology::EdgePoint( topologyNodes[e.first], + topology::EdgePoint::CENTRE)); + for(size_t j=1;j+1<route.size();j++) { + const Avoid::Point& p = route.ps[j]; + const unsigned nodeID=p.id-1; + topology::Node* node=topologyNodes[nodeID]; + topology::EdgePoint::RectIntersect ri; + switch(p.vn) { + case 0: ri=topology::EdgePoint::BR; + break; + case 1: ri=topology::EdgePoint::TR; + break; + case 2: ri=topology::EdgePoint::TL; + break; + case 3: ri=topology::EdgePoint::BL; + break; + default: ri=topology::EdgePoint::CENTRE; + } + eps.push_back(new topology::EdgePoint(node,ri)); + } + eps.push_back(new topology::EdgePoint(topologyNodes[e.second], + topology::EdgePoint::CENTRE)); + topology::Edge* edgeRoute=new topology::Edge(i,defaultEdgeLength, eps); + edgeRoute->assertConvexBends(); + routes.push_back(edgeRoute); + + } + writeFile(topologyNodes,routes,"beautify0.svg"); + assert(topology::assertNoSegmentRectIntersection(topologyNodes,routes)); + double libavoidtime=double(clock()-libavoidstarttime)/double(CLOCKS_PER_SEC); + cout << "done. Libavoid ran in " << libavoidtime << " seconds" << endl; + delete router; +} +int main() { + unsigned V; + CompoundConstraints ccs; + + int seed = time(nullptr); + //seed=1207906420; + //seed=1207920674; + //seed=1207982613; + //seed=1207984219; + seed=1207984299; + //seed=1207984743; + //seed=1207985027; // very short edge which seems to cause problems + //seed=1207986026; // error if we don't check neighbour is actually on scanline when determining visibility when generating straight constraints + //seed=1207991731; + //seed=1208303930; + //seed=1208304508; + //seed=1208316284; + //seed=1208319019; + //seed=1208321702; + printf("random seed=%d\n",seed); + srand(seed); + vector<Edge> es = random_dag(DAGDEPTH,BRANCHFACTOR,V,ccs); + double defaultEdgeLength=40; + + cout << "V="<<V<<endl; + cout << "E="<<es.size()<<endl; + double width=700; + double height=700; + vector<pair<double,double> > startpos(V); + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + startpos[i]=make_pair(x,y); + } + vector<vpsc::Rectangle*> rs; + vector<topology::Node*> topologyNodes; + vector<topology::Edge*> routes; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + vpsc::Rectangle* r =new vpsc::Rectangle(x,x+30,y,y+10); + rs.push_back(r); + topologyNodes.push_back(new topology::Node(i,r)); + } + CheckProgress test(0.01,100); + clock_t unconstrainedstarttime=clock(); + //writeTextFile(es); + es.clear(); + ConstrainedFDLayout alg2(rs,es,defaultEdgeLength,nullptr,test); + //alg2.setConstraints(&ccs); + + alg2.makeFeasible(true); + alg2.run(); + + alg2.outputInstanceToSVG(); +#if 0 + double totaltime=0; + double unconstrainedtime=double(clock()-unconstrainedstarttime)/double(CLOCKS_PER_SEC); + totaltime+=unconstrainedstarttime; + cout<<"unconstrained layout ran in "<<unconstrainedtime<<" seconds"<<endl; + clock_t makefeasiblestarttime=clock(); + makeFeasible(rs,es,routes,topologyNodes,defaultEdgeLength); + double makefeasibletime=double(clock()-makefeasiblestarttime)/double(CLOCKS_PER_SEC); + totaltime+=makefeasibletime; + cout<<"makefeasible ran in "<<makefeasibletime<<" seconds"<<endl; + clock_t beautifystarttime=clock(); + test.reset(); + alg2.setTopology(&topologyNodes, &routes); + writeFile(topologyNodes,routes,"beautify1.svg"); + std::stringstream dunnartfile; + dunnartfile << "v" << V << "e" << (int) es.size() << ".svg"; + writeDunnartFile(topologyNodes,es,dunnartfile.str().c_str()); + + alg2.run(); + double beautifytime=double(clock()-beautifystarttime)/double(CLOCKS_PER_SEC); + totaltime+=beautifytime; + cout<<"beautify ran in "<<beautifytime<<" seconds"<<endl; + cout<<"TOTAL="<<totaltime<<endl; + cout <<"---------------------------------------------"<< endl; + cout <<V<<" & "<<es.size()<<" & "<<unconstrainedtime<<" & "<<makefeasibletime<<" & "<<beautifytime<<" & "<<totaltime<<" \\\\ % Seed: "<< seed <<endl; + writeFile(topologyNodes,routes,"beautify2.svg"); +#endif + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/makefeasible02.cpp b/src/3rdparty/adaptagrams/libcola/tests/makefeasible02.cpp new file mode 100755 index 0000000..82d55b7 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/makefeasible02.cpp @@ -0,0 +1,932 @@ +#include <vector> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + double defaultEdgeLength=40; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + rect = new vpsc::Rectangle(252, 272, 930, 950); + rs.push_back(rect); + + rect = new vpsc::Rectangle(109, 129, 898, 918); + rs.push_back(rect); + + rect = new vpsc::Rectangle(252, 272, 951, 971); + rs.push_back(rect); + + rect = new vpsc::Rectangle(99, 139, 931, 971); + rs.push_back(rect); + + rect = new vpsc::Rectangle(593, 665, 212.5, 459.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(398, 518, 52, 96); + rs.push_back(rect); + + rect = new vpsc::Rectangle(341, 361, 899, 919); + rs.push_back(rect); + + rect = new vpsc::Rectangle(450, 470, 930, 950); + rs.push_back(rect); + + rect = new vpsc::Rectangle(402, 422, 930, 950); + rs.push_back(rect); + + rect = new vpsc::Rectangle(394, 414, 861, 881); + rs.push_back(rect); + + rect = new vpsc::Rectangle(394, 414, 840, 860); + rs.push_back(rect); + + rect = new vpsc::Rectangle(282, 302, 852, 872); + rs.push_back(rect); + + rect = new vpsc::Rectangle(173, 193, 852, 872); + rs.push_back(rect); + + rect = new vpsc::Rectangle(521, 541, 851, 871); + rs.push_back(rect); + + rect = new vpsc::Rectangle(313, 401, 739, 783); + rs.push_back(rect); + + rect = new vpsc::Rectangle(446, 466, 757, 777); + rs.push_back(rect); + + rect = new vpsc::Rectangle(446, 466, 688, 708); + rs.push_back(rect); + + rect = new vpsc::Rectangle(447, 467, 616, 636); + rs.push_back(rect); + + rect = new vpsc::Rectangle(421, 441, 471, 491); + rs.push_back(rect); + + rect = new vpsc::Rectangle(196.5, 359.5, 575, 619); + rs.push_back(rect); + + rect = new vpsc::Rectangle(366, 386, 437, 457); + rs.push_back(rect); + + rect = new vpsc::Rectangle(446, 466, 391, 411); + rs.push_back(rect); + + rect = new vpsc::Rectangle(446, 466, 325, 345); + rs.push_back(rect); + + rect = new vpsc::Rectangle(393, 413, 325, 345); + rs.push_back(rect); + + rect = new vpsc::Rectangle(515, 535, 182, 202); + rs.push_back(rect); + + rect = new vpsc::Rectangle(446, 466, 255, 275); + rs.push_back(rect); + + rect = new vpsc::Rectangle(446, 466, 160, 180); + rs.push_back(rect); + + rect = new vpsc::Rectangle(366, 386, 289, 309); + rs.push_back(rect); + + rect = new vpsc::Rectangle(211, 231, 270, 290); + rs.push_back(rect); + + rect = new vpsc::Rectangle(211, 231, 289, 309); + rs.push_back(rect); + + rect = new vpsc::Rectangle(320, 340, 256, 276); + rs.push_back(rect); + + rect = new vpsc::Rectangle(270, 290, 256, 276); + rs.push_back(rect); + + rect = new vpsc::Rectangle(144, 164, 251, 271); + rs.push_back(rect); + + rect = new vpsc::Rectangle(211, 231, 214, 234); + rs.push_back(rect); + + rect = new vpsc::Rectangle(211, 231, 195, 215); + rs.push_back(rect); + + rect = new vpsc::Rectangle(279, 299, 173, 193); + rs.push_back(rect); + + rect = new vpsc::Rectangle(306, 326, 141, 161); + rs.push_back(rect); + + rect = new vpsc::Rectangle(306, 326, 120, 140); + rs.push_back(rect); + + rect = new vpsc::Rectangle(34.5, 295.5, 39.5, 74.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(225, 245, 895, 915); + rs.push_back(rect); + + rect = new vpsc::Rectangle(446, 466, 543, 563); + rs.push_back(rect); + + rect = new vpsc::Rectangle(211, 231, 233, 253); + rs.push_back(rect); + + rect = new vpsc::Rectangle(211, 231, 308, 328); + rs.push_back(rect); + + rect = new vpsc::Rectangle(144, 164, 347, 367); + rs.push_back(rect); + + rect = new vpsc::Rectangle(144, 164, 373, 393); + rs.push_back(rect); + + rect = new vpsc::Rectangle(254, 274, 346, 366); + rs.push_back(rect); + + rect = new vpsc::Rectangle(254, 274, 372, 392); + rs.push_back(rect); + + rect = new vpsc::Rectangle(554, 594, 173, 213); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 121, 161); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 642, 682); + rs.push_back(rect); + + rect = new vpsc::Rectangle(134, 174, 206, 246); + rs.push_back(rect); + + rect = new vpsc::Rectangle(134, 174, 279, 319); + rs.push_back(rect); + + rect = new vpsc::Rectangle(285, 325, 426, 466); + rs.push_back(rect); + + rect = new vpsc::Rectangle(285, 325, 279, 319); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 208, 248); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 281, 321); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 714, 754); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 570, 610); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 498, 538); + rs.push_back(rect); + + rect = new vpsc::Rectangle(580, 620, 841, 881); + rs.push_back(rect); + + rect = new vpsc::Rectangle(267, 307, 884, 924); + rs.push_back(rect); + + rect = new vpsc::Rectangle(503, 543, 931, 971); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 841, 881); + rs.push_back(rect); + + rect = new vpsc::Rectangle(331, 371, 841, 881); + rs.push_back(rect); + + rect = new vpsc::Rectangle(331, 371, 798, 838); + rs.push_back(rect); + + rect = new vpsc::Rectangle(99, 139, 841, 881); + rs.push_back(rect); + + rect = new vpsc::Rectangle(331, 371, 931, 971); + rs.push_back(rect); + + rect = new vpsc::Rectangle(218, 258, 841, 881); + rs.push_back(rect); + + rect = new vpsc::Rectangle(165, 205, 884, 924); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 351, 391); + rs.push_back(rect); + + rect = new vpsc::Rectangle(85, 125, 336, 376); + rs.push_back(rect); + + rect = new vpsc::Rectangle(192, 232, 336, 376); + rs.push_back(rect); + + rect = new vpsc::Rectangle(192, 232, 362, 402); + rs.push_back(rect); + + rect = new vpsc::Rectangle(85, 125, 362, 402); + rs.push_back(rect); + + rect = new vpsc::Rectangle(20.5, 77.5, 716, 880); + rs.push_back(rect); + + rect = new vpsc::Rectangle(167, 187, 713, 733); + rs.push_back(rect); + + rect = new vpsc::Rectangle(99, 139, 714, 754); + rs.push_back(rect); + + rect = new vpsc::Rectangle(402, 422, 951, 971); + rs.push_back(rect); + + rect = new vpsc::Rectangle(167, 187, 734, 754); + rs.push_back(rect); + + rect = new vpsc::Rectangle(450, 470, 951, 971); + rs.push_back(rect); + + rect = new vpsc::Rectangle(532.5, 669.5, 899.5, 934.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(471, 491, 471, 491); + rs.push_back(rect); + + rect = new vpsc::Rectangle(545, 565, 512, 532); + rs.push_back(rect); + + rect = new vpsc::Rectangle(518, 538, 531, 551); + rs.push_back(rect); + + rect = new vpsc::Rectangle(252, 272, 782, 802); + rs.push_back(rect); + + rect = new vpsc::Rectangle(495, 515, 512, 532); + rs.push_back(rect); + + rect = new vpsc::Rectangle(351, 391, 534, 574); + rs.push_back(rect); + + rect = new vpsc::Rectangle(400, 420, 573, 593); + rs.push_back(rect); + + rect = new vpsc::Rectangle(401, 421, 509, 529); + rs.push_back(rect); + + rect = new vpsc::Rectangle(436, 476, 426, 466); + rs.push_back(rect); + + rect = new vpsc::Rectangle(234, 290, 970, 1010); + rs.push_back(rect); + + rect = new vpsc::Rectangle(29, 85, 888, 928); + rs.push_back(rect); + + rect = new vpsc::Rectangle(234, 290, 991, 1031); + rs.push_back(rect); + + rect = new vpsc::Rectangle(261, 317, 889, 929); + rs.push_back(rect); + + rect = new vpsc::Rectangle(432, 488, 870, 910); + rs.push_back(rect); + + rect = new vpsc::Rectangle(384, 440, 970, 1010); + rs.push_back(rect); + + rect = new vpsc::Rectangle(314, 370, 851, 891); + rs.push_back(rect); + + rect = new vpsc::Rectangle(438, 494, 830, 870); + rs.push_back(rect); + + rect = new vpsc::Rectangle(202, 258, 842, 882); + rs.push_back(rect); + + rect = new vpsc::Rectangle(155, 211, 792, 832); + rs.push_back(rect); + + rect = new vpsc::Rectangle(503, 559, 791, 831); + rs.push_back(rect); + + rect = new vpsc::Rectangle(490, 546, 747, 787); + rs.push_back(rect); + + rect = new vpsc::Rectangle(366, 422, 678, 718); + rs.push_back(rect); + + rect = new vpsc::Rectangle(367, 423, 606, 646); + rs.push_back(rect); + + rect = new vpsc::Rectangle(341, 397, 461, 501); + rs.push_back(rect); + + rect = new vpsc::Rectangle(348, 404, 377, 417); + rs.push_back(rect); + + rect = new vpsc::Rectangle(490, 546, 381, 421); + rs.push_back(rect); + + rect = new vpsc::Rectangle(490, 546, 315, 355); + rs.push_back(rect); + + rect = new vpsc::Rectangle(375, 431, 365, 405); + rs.push_back(rect); + + rect = new vpsc::Rectangle(497, 553, 122, 162); + rs.push_back(rect); + + rect = new vpsc::Rectangle(490, 546, 245, 285); + rs.push_back(rect); + + rect = new vpsc::Rectangle(366, 422, 150, 190); + rs.push_back(rect); + + rect = new vpsc::Rectangle(348, 404, 229, 269); + rs.push_back(rect); + + rect = new vpsc::Rectangle(193, 249, 210, 250); + rs.push_back(rect); + + rect = new vpsc::Rectangle(193, 249, 229, 269); + rs.push_back(rect); + + rect = new vpsc::Rectangle(364, 420, 246, 286); + rs.push_back(rect); + + rect = new vpsc::Rectangle(190, 246, 246, 286); + rs.push_back(rect); + + rect = new vpsc::Rectangle(64, 120, 241, 281); + rs.push_back(rect); + + rect = new vpsc::Rectangle(193, 249, 154, 194); + rs.push_back(rect); + + rect = new vpsc::Rectangle(193, 249, 135, 175); + rs.push_back(rect); + + rect = new vpsc::Rectangle(261, 317, 213, 253); + rs.push_back(rect); + + rect = new vpsc::Rectangle(288, 344, 81, 121); + rs.push_back(rect); + + rect = new vpsc::Rectangle(288, 344, 160, 200); + rs.push_back(rect); + + rect = new vpsc::Rectangle(207, 263, 835, 875); + rs.push_back(rect); + + rect = new vpsc::Rectangle(366, 422, 533, 573); + rs.push_back(rect); + + rect = new vpsc::Rectangle(193, 249, 173, 213); + rs.push_back(rect); + + rect = new vpsc::Rectangle(193, 249, 248, 288); + rs.push_back(rect); + + rect = new vpsc::Rectangle(126, 182, 287, 327); + rs.push_back(rect); + + rect = new vpsc::Rectangle(126, 182, 413, 453); + rs.push_back(rect); + + rect = new vpsc::Rectangle(236, 292, 286, 326); + rs.push_back(rect); + + rect = new vpsc::Rectangle(236, 292, 412, 452); + rs.push_back(rect); + + rect = new vpsc::Rectangle(149, 205, 653, 693); + rs.push_back(rect); + + rect = new vpsc::Rectangle(384, 440, 891, 931); + rs.push_back(rect); + + rect = new vpsc::Rectangle(149, 205, 674, 714); + rs.push_back(rect); + + rect = new vpsc::Rectangle(432, 488, 991, 1031); + rs.push_back(rect); + + rect = new vpsc::Rectangle(515, 571, 461, 501); + rs.push_back(rect); + + rect = new vpsc::Rectangle(527, 583, 452, 492); + rs.push_back(rect); + + rect = new vpsc::Rectangle(500, 556, 571, 611); + rs.push_back(rect); + + rect = new vpsc::Rectangle(234, 290, 722, 762); + rs.push_back(rect); + + rect = new vpsc::Rectangle(539, 595, 502, 542); + rs.push_back(rect); + + rect = new vpsc::Rectangle(382, 438, 613, 653); + rs.push_back(rect); + + rect = new vpsc::Rectangle(383, 439, 449, 489); + rs.push_back(rect); + +#if 1 + AlignmentConstraint *alignment2424608 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment2424608->addShape(0, 0); + alignment2424608->addShape(2, 0); + alignment2424608->addShape(45, 0); + alignment2424608->addShape(46, 0); + alignment2424608->addShape(84, 0); + alignment2424608->addShape(90, 0); + alignment2424608->addShape(92, 0); + alignment2424608->addShape(129, 0); + alignment2424608->addShape(130, 0); + alignment2424608->addShape(138, 0); + ccs.push_back(alignment2424608); + AlignmentConstraint *alignment2424744 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment2424744->addShape(1, 0); + alignment2424744->addShape(3, 0); + alignment2424744->addShape(65, 0); + alignment2424744->addShape(76, 0); + ccs.push_back(alignment2424744); + AlignmentConstraint *alignment1216038856 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216038856->addShape(4, 0); + ccs.push_back(alignment1216038856); + AlignmentConstraint *alignment1216038920 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216038920->addShape(5, 0); + alignment1216038920->addShape(7, 0); + alignment1216038920->addShape(15, 0); + alignment1216038920->addShape(16, 0); + alignment1216038920->addShape(17, 0); + alignment1216038920->addShape(21, 0); + alignment1216038920->addShape(22, 0); + alignment1216038920->addShape(25, 0); + alignment1216038920->addShape(26, 0); + alignment1216038920->addShape(40, 0); + alignment1216038920->addShape(48, 0); + alignment1216038920->addShape(49, 0); + alignment1216038920->addShape(54, 0); + alignment1216038920->addShape(55, 0); + alignment1216038920->addShape(56, 0); + alignment1216038920->addShape(57, 0); + alignment1216038920->addShape(58, 0); + alignment1216038920->addShape(62, 0); + alignment1216038920->addShape(69, 0); + alignment1216038920->addShape(79, 0); + alignment1216038920->addShape(89, 0); + alignment1216038920->addShape(94, 0); + alignment1216038920->addShape(134, 0); + ccs.push_back(alignment1216038920); + AlignmentConstraint *alignment1216038984 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216038984->addShape(6, 0); + alignment1216038984->addShape(63, 0); + alignment1216038984->addShape(64, 0); + alignment1216038984->addShape(66, 0); + ccs.push_back(alignment1216038984); + AlignmentConstraint *alignment1216039048 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216039048->addShape(8, 0); + alignment1216039048->addShape(77, 0); + alignment1216039048->addShape(87, 0); + alignment1216039048->addShape(88, 0); + alignment1216039048->addShape(95, 0); + alignment1216039048->addShape(132, 0); + alignment1216039048->addShape(140, 0); + alignment1216039048->addShape(141, 0); + ccs.push_back(alignment1216039048); + AlignmentConstraint *alignment1216039112 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216039112->addShape(9, 0); + alignment1216039112->addShape(10, 0); + alignment1216039112->addShape(23, 0); + alignment1216039112->addShape(108, 0); + ccs.push_back(alignment1216039112); + AlignmentConstraint *alignment1216039176 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216039176->addShape(11, 0); + alignment1216039176->addShape(35, 0); + alignment1216039176->addShape(60, 0); + alignment1216039176->addShape(93, 0); + alignment1216039176->addShape(120, 0); + ccs.push_back(alignment1216039176); + AlignmentConstraint *alignment1216039240 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216039240->addShape(12, 0); + alignment1216039240->addShape(68, 0); + alignment1216039240->addShape(99, 0); + ccs.push_back(alignment1216039240); + AlignmentConstraint *alignment1216039304 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216039304->addShape(13, 0); + alignment1216039304->addShape(83, 0); + alignment1216039304->addShape(100, 0); + alignment1216039304->addShape(137, 0); + ccs.push_back(alignment1216039304); + AlignmentConstraint *alignment1216040464 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216040464->addShape(14, 0); + ccs.push_back(alignment1216040464); + AlignmentConstraint *alignment1216040528 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216040528->addShape(18, 0); + ccs.push_back(alignment1216040528); + AlignmentConstraint *alignment1216040592 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216040592->addShape(19, 0); + alignment1216040592->addShape(31, 0); + ccs.push_back(alignment1216040592); + AlignmentConstraint *alignment1216040656 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216040656->addShape(20, 0); + alignment1216040656->addShape(27, 0); + alignment1216040656->addShape(86, 0); + alignment1216040656->addShape(105, 0); + alignment1216040656->addShape(112, 0); + ccs.push_back(alignment1216040656); + AlignmentConstraint *alignment1216040720 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216040720->addShape(24, 0); + alignment1216040720->addShape(61, 0); + alignment1216040720->addShape(109, 0); + ccs.push_back(alignment1216040720); + AlignmentConstraint *alignment1216040784 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216040784->addShape(28, 0); + alignment1216040784->addShape(29, 0); + alignment1216040784->addShape(33, 0); + alignment1216040784->addShape(34, 0); + alignment1216040784->addShape(41, 0); + alignment1216040784->addShape(42, 0); + alignment1216040784->addShape(113, 0); + alignment1216040784->addShape(114, 0); + alignment1216040784->addShape(116, 0); + alignment1216040784->addShape(118, 0); + alignment1216040784->addShape(119, 0); + alignment1216040784->addShape(125, 0); + alignment1216040784->addShape(126, 0); + ccs.push_back(alignment1216040784); + AlignmentConstraint *alignment1216034032 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216034032->addShape(30, 0); + ccs.push_back(alignment1216034032); + AlignmentConstraint *alignment1216035736 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035736->addShape(32, 0); + alignment1216035736->addShape(43, 0); + alignment1216035736->addShape(44, 0); + alignment1216035736->addShape(50, 0); + alignment1216035736->addShape(51, 0); + alignment1216035736->addShape(127, 0); + alignment1216035736->addShape(128, 0); + ccs.push_back(alignment1216035736); + AlignmentConstraint *alignment1216035800 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035800->addShape(36, 0); + alignment1216035800->addShape(37, 0); + alignment1216035800->addShape(121, 0); + alignment1216035800->addShape(122, 0); + ccs.push_back(alignment1216035800); + AlignmentConstraint *alignment1216035864 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035864->addShape(38, 0); + ccs.push_back(alignment1216035864); + AlignmentConstraint *alignment1216035928 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035928->addShape(39, 0); + alignment1216035928->addShape(67, 0); + alignment1216035928->addShape(98, 0); + alignment1216035928->addShape(123, 0); + ccs.push_back(alignment1216035928); + AlignmentConstraint *alignment1216035992 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035992->addShape(47, 0); + ccs.push_back(alignment1216035992); + AlignmentConstraint *alignment1216036056 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036056->addShape(52, 0); + alignment1216036056->addShape(53, 0); + ccs.push_back(alignment1216036056); + AlignmentConstraint *alignment1216036120 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036120->addShape(59, 0); + alignment1216036120->addShape(80, 0); + ccs.push_back(alignment1216036120); + AlignmentConstraint *alignment1216036184 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036184->addShape(70, 0); + alignment1216036184->addShape(73, 0); + ccs.push_back(alignment1216036184); + AlignmentConstraint *alignment1216036248 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036248->addShape(71, 0); + alignment1216036248->addShape(72, 0); + ccs.push_back(alignment1216036248); + AlignmentConstraint *alignment1216036312 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036312->addShape(74, 0); + ccs.push_back(alignment1216036312); + AlignmentConstraint *alignment1216036376 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036376->addShape(75, 0); + alignment1216036376->addShape(78, 0); + alignment1216036376->addShape(131, 0); + alignment1216036376->addShape(133, 0); + ccs.push_back(alignment1216036376); + AlignmentConstraint *alignment1216036440 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036440->addShape(81, 0); + ccs.push_back(alignment1216036440); + AlignmentConstraint *alignment1216036504 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036504->addShape(82, 0); + alignment1216036504->addShape(136, 0); + ccs.push_back(alignment1216036504); + AlignmentConstraint *alignment1216036568 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036568->addShape(85, 0); + ccs.push_back(alignment1216036568); + AlignmentConstraint *alignment1216036632 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216036632->addShape(91, 0); + ccs.push_back(alignment1216036632); + AlignmentConstraint *alignment1216034712 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216034712->addShape(96, 0); + ccs.push_back(alignment1216034712); + AlignmentConstraint *alignment1216034776 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216034776->addShape(97, 0); + ccs.push_back(alignment1216034776); + AlignmentConstraint *alignment1216034840 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216034840->addShape(101, 0); + alignment1216034840->addShape(106, 0); + alignment1216034840->addShape(107, 0); + alignment1216034840->addShape(110, 0); + ccs.push_back(alignment1216034840); + AlignmentConstraint *alignment1216034904 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216034904->addShape(102, 0); + alignment1216034904->addShape(103, 0); + alignment1216034904->addShape(111, 0); + alignment1216034904->addShape(115, 0); + alignment1216034904->addShape(124, 0); + ccs.push_back(alignment1216034904); + AlignmentConstraint *alignment1216034968 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216034968->addShape(104, 0); + ccs.push_back(alignment1216034968); + AlignmentConstraint *alignment1216035032 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035032->addShape(117, 0); + ccs.push_back(alignment1216035032); + AlignmentConstraint *alignment1216035096 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035096->addShape(135, 0); + ccs.push_back(alignment1216035096); + AlignmentConstraint *alignment1216035160 = new AlignmentConstraint((vpsc::Dim) 0, 0); + alignment1216035160->addShape(139, 0); + ccs.push_back(alignment1216035160); +#endif + +#if 1 + AlignmentConstraint *alignment1216035224 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216035224->addShape(0, 0); + alignment1216035224->addShape(7, 0); + alignment1216035224->addShape(8, 0); + ccs.push_back(alignment1216035224); + AlignmentConstraint *alignment1216035288 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216035288->addShape(1, 0); + alignment1216035288->addShape(6, 0); + alignment1216035288->addShape(39, 0); + alignment1216035288->addShape(60, 0); + alignment1216035288->addShape(68, 0); + alignment1216035288->addShape(91, 0); + alignment1216035288->addShape(93, 0); + alignment1216035288->addShape(132, 0); + ccs.push_back(alignment1216035288); + AlignmentConstraint *alignment1216035352 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216035352->addShape(2, 0); + alignment1216035352->addShape(77, 0); + alignment1216035352->addShape(79, 0); + ccs.push_back(alignment1216035352); + AlignmentConstraint *alignment1216035416 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216035416->addShape(3, 0); + alignment1216035416->addShape(61, 0); + alignment1216035416->addShape(66, 0); + ccs.push_back(alignment1216035416); + AlignmentConstraint *alignment1216035480 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216035480->addShape(4, 0); + alignment1216035480->addShape(22, 0); + alignment1216035480->addShape(23, 0); + alignment1216035480->addShape(107, 0); + ccs.push_back(alignment1216035480); + AlignmentConstraint *alignment1216035544 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216035544->addShape(5, 0); + ccs.push_back(alignment1216035544); + AlignmentConstraint *alignment1216035608 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216035608->addShape(9, 0); + alignment1216035608->addShape(96, 0); + ccs.push_back(alignment1216035608); + AlignmentConstraint *alignment1216042672 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216042672->addShape(10, 0); + alignment1216042672->addShape(97, 0); + alignment1216042672->addShape(123, 0); + ccs.push_back(alignment1216042672); + AlignmentConstraint *alignment1216042736 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216042736->addShape(11, 0); + alignment1216042736->addShape(12, 0); + alignment1216042736->addShape(13, 0); + alignment1216042736->addShape(59, 0); + alignment1216042736->addShape(62, 0); + alignment1216042736->addShape(63, 0); + alignment1216042736->addShape(65, 0); + alignment1216042736->addShape(67, 0); + alignment1216042736->addShape(98, 0); + ccs.push_back(alignment1216042736); + AlignmentConstraint *alignment1216042800 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216042800->addShape(14, 0); + ccs.push_back(alignment1216042800); + AlignmentConstraint *alignment1216042864 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216042864->addShape(15, 0); + alignment1216042864->addShape(101, 0); + ccs.push_back(alignment1216042864); + AlignmentConstraint *alignment1216042928 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216042928->addShape(16, 0); + alignment1216042928->addShape(102, 0); + alignment1216042928->addShape(133, 0); + ccs.push_back(alignment1216042928); + AlignmentConstraint *alignment1216042992 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216042992->addShape(17, 0); + alignment1216042992->addShape(103, 0); + ccs.push_back(alignment1216042992); + AlignmentConstraint *alignment1216043056 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043056->addShape(18, 0); + alignment1216043056->addShape(81, 0); + alignment1216043056->addShape(104, 0); + alignment1216043056->addShape(135, 0); + ccs.push_back(alignment1216043056); + AlignmentConstraint *alignment1216043120 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043120->addShape(19, 0); + ccs.push_back(alignment1216043120); + AlignmentConstraint *alignment1216043184 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043184->addShape(20, 0); + alignment1216043184->addShape(52, 0); + alignment1216043184->addShape(89, 0); + ccs.push_back(alignment1216043184); + AlignmentConstraint *alignment1216043248 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043248->addShape(21, 0); + alignment1216043248->addShape(105, 0); + alignment1216043248->addShape(106, 0); + ccs.push_back(alignment1216043248); + AlignmentConstraint *alignment1216043312 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043312->addShape(24, 0); + alignment1216043312->addShape(47, 0); + alignment1216043312->addShape(125, 0); + ccs.push_back(alignment1216043312); + AlignmentConstraint *alignment1216043376 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043376->addShape(25, 0); + alignment1216043376->addShape(30, 0); + alignment1216043376->addShape(31, 0); + alignment1216043376->addShape(32, 0); + alignment1216043376->addShape(110, 0); + alignment1216043376->addShape(115, 0); + alignment1216043376->addShape(116, 0); + alignment1216043376->addShape(117, 0); + alignment1216043376->addShape(126, 0); + ccs.push_back(alignment1216043376); + AlignmentConstraint *alignment1216043440 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043440->addShape(26, 0); + alignment1216043440->addShape(111, 0); + alignment1216043440->addShape(118, 0); + ccs.push_back(alignment1216043440); + AlignmentConstraint *alignment1216043504 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043504->addShape(27, 0); + alignment1216043504->addShape(29, 0); + alignment1216043504->addShape(51, 0); + alignment1216043504->addShape(53, 0); + alignment1216043504->addShape(55, 0); + ccs.push_back(alignment1216043504); + AlignmentConstraint *alignment1216043568 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043568->addShape(28, 0); + ccs.push_back(alignment1216043568); + AlignmentConstraint *alignment1216043632 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043632->addShape(33, 0); + alignment1216043632->addShape(50, 0); + alignment1216043632->addShape(54, 0); + ccs.push_back(alignment1216043632); + AlignmentConstraint *alignment1216043696 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043696->addShape(34, 0); + ccs.push_back(alignment1216043696); + AlignmentConstraint *alignment1216043760 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043760->addShape(35, 0); + alignment1216043760->addShape(122, 0); + ccs.push_back(alignment1216043760); + AlignmentConstraint *alignment1216043824 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043824->addShape(36, 0); + alignment1216043824->addShape(119, 0); + ccs.push_back(alignment1216043824); + AlignmentConstraint *alignment1216043888 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043888->addShape(37, 0); + ccs.push_back(alignment1216043888); + AlignmentConstraint *alignment1216043952 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216043952->addShape(38, 0); + ccs.push_back(alignment1216043952); + AlignmentConstraint *alignment1216044016 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044016->addShape(40, 0); + alignment1216044016->addShape(86, 0); + alignment1216044016->addShape(124, 0); + ccs.push_back(alignment1216044016); + AlignmentConstraint *alignment1216044080 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044080->addShape(41, 0); + ccs.push_back(alignment1216044080); + AlignmentConstraint *alignment1216044144 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044144->addShape(42, 0); + ccs.push_back(alignment1216044144); + AlignmentConstraint *alignment1216044208 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044208->addShape(43, 0); + alignment1216044208->addShape(45, 0); + alignment1216044208->addShape(70, 0); + alignment1216044208->addShape(71, 0); + ccs.push_back(alignment1216044208); + AlignmentConstraint *alignment1216044272 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044272->addShape(44, 0); + alignment1216044272->addShape(46, 0); + alignment1216044272->addShape(72, 0); + alignment1216044272->addShape(73, 0); + alignment1216044272->addShape(108, 0); + ccs.push_back(alignment1216044272); + AlignmentConstraint *alignment1216044336 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044336->addShape(48, 0); + alignment1216044336->addShape(109, 0); + ccs.push_back(alignment1216044336); + AlignmentConstraint *alignment1216044400 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044400->addShape(49, 0); + ccs.push_back(alignment1216044400); + AlignmentConstraint *alignment1216044464 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044464->addShape(56, 0); + alignment1216044464->addShape(76, 0); + ccs.push_back(alignment1216044464); + AlignmentConstraint *alignment1216044528 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044528->addShape(57, 0); + alignment1216044528->addShape(137, 0); + ccs.push_back(alignment1216044528); + AlignmentConstraint *alignment1216044592 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216044592->addShape(58, 0); + alignment1216044592->addShape(82, 0); + alignment1216044592->addShape(85, 0); + alignment1216044592->addShape(88, 0); + alignment1216044592->addShape(139, 0); + ccs.push_back(alignment1216044592); + AlignmentConstraint *alignment1216021552 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216021552->addShape(64, 0); + ccs.push_back(alignment1216021552); + AlignmentConstraint *alignment1216021616 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216021616->addShape(69, 0); + ccs.push_back(alignment1216021616); + AlignmentConstraint *alignment1216021680 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216021680->addShape(74, 0); + ccs.push_back(alignment1216021680); + AlignmentConstraint *alignment1216021744 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216021744->addShape(75, 0); + ccs.push_back(alignment1216021744); + AlignmentConstraint *alignment1216021808 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216021808->addShape(78, 0); + alignment1216021808->addShape(138, 0); + ccs.push_back(alignment1216021808); + AlignmentConstraint *alignment1216021872 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216021872->addShape(80, 0); + ccs.push_back(alignment1216021872); + AlignmentConstraint *alignment1216021936 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216021936->addShape(83, 0); + ccs.push_back(alignment1216021936); + AlignmentConstraint *alignment1216022000 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022000->addShape(84, 0); + ccs.push_back(alignment1216022000); + AlignmentConstraint *alignment1216022064 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022064->addShape(87, 0); + ccs.push_back(alignment1216022064); + AlignmentConstraint *alignment1216022128 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022128->addShape(90, 0); + alignment1216022128->addShape(95, 0); + ccs.push_back(alignment1216022128); + AlignmentConstraint *alignment1216022192 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022192->addShape(92, 0); + alignment1216022192->addShape(134, 0); + ccs.push_back(alignment1216022192); + AlignmentConstraint *alignment1216022256 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022256->addShape(94, 0); + ccs.push_back(alignment1216022256); + AlignmentConstraint *alignment1216022320 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022320->addShape(99, 0); + alignment1216022320->addShape(100, 0); + ccs.push_back(alignment1216022320); + AlignmentConstraint *alignment1216022384 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022384->addShape(112, 0); + alignment1216022384->addShape(114, 0); + ccs.push_back(alignment1216022384); + AlignmentConstraint *alignment1216022448 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022448->addShape(113, 0); + alignment1216022448->addShape(120, 0); + ccs.push_back(alignment1216022448); + AlignmentConstraint *alignment1216022512 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022512->addShape(121, 0); + ccs.push_back(alignment1216022512); + AlignmentConstraint *alignment1216022576 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022576->addShape(127, 0); + alignment1216022576->addShape(129, 0); + ccs.push_back(alignment1216022576); + AlignmentConstraint *alignment1216022640 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022640->addShape(128, 0); + alignment1216022640->addShape(130, 0); + ccs.push_back(alignment1216022640); + AlignmentConstraint *alignment1216022704 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022704->addShape(131, 0); + ccs.push_back(alignment1216022704); + AlignmentConstraint *alignment1216022768 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022768->addShape(136, 0); + alignment1216022768->addShape(141, 0); + ccs.push_back(alignment1216022768); + AlignmentConstraint *alignment1216022832 = new AlignmentConstraint((vpsc::Dim) 1, 0); + alignment1216022832->addShape(140, 0); + ccs.push_back(alignment1216022832); +#endif + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength); + alg.setAvoidNodeOverlaps(true); + alg.setConstraints(ccs); + alg.makeFeasible(); + alg.outputInstanceToSVG(); + //alg.run(); + return 0; +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/makemovie.sh b/src/3rdparty/adaptagrams/libcola/tests/makemovie.sh new file mode 100644 index 0000000..cd571f9 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/makemovie.sh @@ -0,0 +1,10 @@ +pattern=containment +width=200 +height=260 +rm ${pattern}*.pdf +for file in ${pattern}*.svg +do + echo adding $file... + inkscape -w$width -h$height -A ${file%.svg}.pdf $file 2> /dev/null +done +convert -page ${width}x${height} -delay 15 ${pattern}*.pdf $pattern.gif diff --git a/src/3rdparty/adaptagrams/libcola/tests/max_acyclic_subgraph.cpp b/src/3rdparty/adaptagrams/libcola/tests/max_acyclic_subgraph.cpp new file mode 100644 index 0000000..cb2eb38 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/max_acyclic_subgraph.cpp @@ -0,0 +1,346 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <iostream> +#include <vector> +#include <assert.h> +#include <libcola/cola.h> +#include <libcola/max_acyclic_subgraph.h> +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; +using vpsc::Rectangle; + +int main() { + MaxAcyclicSubgraph *mas; + Edges case_a, case_b, case_c, case_d, case_e, case_f; + Edges *subgraph = nullptr; + + vector<Rectangle *> rs; + unsigned V; + + // create case A + // case A consists of a basic graph where the start point is a source + cout << endl << "ENTERING CASE A" << endl; + V = 5; + case_a.push_back(Edge(0, 1)); + case_a.push_back(Edge(1, 2)); + case_a.push_back(Edge(2, 3)); + case_a.push_back(Edge(3, 4)); + case_a.push_back(Edge(4, 1)); + + // detect the subgraph + mas = new MaxAcyclicSubgraph(V, &case_a); + subgraph = mas->find_subgraph(); + + if (subgraph != nullptr) { + cout << "subgraph->size(): " << subgraph->size() << endl; + cout << "Ea: "; + for (unsigned i = 0; i < subgraph->size(); i++) { + // print out the subgraph + cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") "; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); + rs.push_back(new Rectangle(30,30+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,30,30+5)); + + assert(rs.size() == V); + + output_svg(rs, case_a, "mas_case_a.svg", false, true, subgraph); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + + delete subgraph; + } + else { + cout << "No subgraph found" << endl; + } + + // create case B + // case B is the same graph of case A but with more elements + cout << endl << "ENTERING CASE B" << endl; + V = 7; + case_b.push_back(Edge(0, 1)); + case_b.push_back(Edge(1, 2)); + case_b.push_back(Edge(2, 3)); + case_b.push_back(Edge(3, 4)); + case_b.push_back(Edge(4, 1)); + case_b.push_back(Edge(5, 2)); + case_b.push_back(Edge(6, 5)); + + // detect the subgraph + mas->mod_graph(V, &case_b); + subgraph = mas->find_subgraph(); + + if (subgraph != nullptr) { + cout << "subgraph->size(): " << subgraph->size() << endl; + cout << "Ea: "; + for (unsigned i = 0; i < subgraph->size(); i++) { + // print out the subgraph + cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") "; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); + rs.push_back(new Rectangle(30,30+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,90,90+5)); + rs.push_back(new Rectangle(65,65+5,90,90+5)); + + assert(rs.size() == V); + + output_svg(rs, case_b, "mas_case_b.svg", false, true, subgraph); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + + delete subgraph; + } + else { + cout << "No subgraph found" << endl; + } + + // create case C + // case C is a more complicated graph with nested subgraph + cout << endl << "ENTERING CASE C" << endl; + V = 14; + case_c.push_back(Edge(0, 1)); + case_c.push_back(Edge(0, 5)); + case_c.push_back(Edge(0, 6)); + case_c.push_back(Edge(2, 0)); + case_c.push_back(Edge(3, 5)); + case_c.push_back(Edge(4, 3)); + case_c.push_back(Edge(5, 4)); + case_c.push_back(Edge(5, 13)); + case_c.push_back(Edge(6, 2)); + case_c.push_back(Edge(6, 9)); + case_c.push_back(Edge(7, 6)); + case_c.push_back(Edge(8, 7)); + case_c.push_back(Edge(9, 10)); + case_c.push_back(Edge(9, 11)); + case_c.push_back(Edge(9, 12)); + case_c.push_back(Edge(10, 6)); + case_c.push_back(Edge(12, 10)); + case_c.push_back(Edge(13, 4)); + + // detect the subgraph + mas->mod_graph(V, &case_c); + subgraph = mas->find_subgraph(); + + if (subgraph != nullptr) { + cout << "subgraph->size(): " << subgraph->size() << endl; + cout << "Ea: "; + for (unsigned i = 0; i < subgraph->size(); i++) { + // print out the subgraph + cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") "; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0 + rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1 + rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2 + rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3 + rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4 + rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5 + rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6 + rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7 + rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8 + rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9 + rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10 + rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11 + rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12 + rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13 + + assert(rs.size() == V); + + output_svg(rs, case_c, "mas_case_c.svg", false, true, subgraph); + for(int i = 0; i < V; i++) { delete rs[i]; } + rs.clear(); + delete subgraph; + } + else { + cout << "No subgraph found" << endl; + } + + // create case D + // case D consists of the same graph as case A but with a different starting location + cout << endl << "ENTERING CASE D" << endl; + V = 5; + case_d.push_back(Edge(0, 1)); + case_d.push_back(Edge(1, 2)); + case_d.push_back(Edge(2, 3)); + case_d.push_back(Edge(3, 0)); + case_d.push_back(Edge(4, 1)); + + // detect the subgraph + mas->mod_graph(V, &case_d); + subgraph = mas->find_subgraph(); + + if (subgraph != nullptr) { + cout << "subgraph->size(): " << subgraph->size() << endl; + cout << "Ea: "; + for (unsigned i = 0; i < subgraph->size(); i++) { + // print out the subgraph + cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") "; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(65,65+5,60,60+5)); + rs.push_back(new Rectangle(65,65+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,30,30+5)); + rs.push_back(new Rectangle(30,30+5,60,60+5)); + rs.push_back(new Rectangle(10,10+5,10,10+5)); + + assert(rs.size() == V); + + output_svg(rs, case_d, "mas_case_d.svg", false, true, subgraph); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + delete subgraph; + } + else { + cout << "No subgraph found" << endl; + } + + // create case E + // case E is a reordering of case C + cout << endl << "ENTERING CASE E" << endl; + V = 14; + case_e.push_back(Edge(0, 6)); + case_e.push_back(Edge(0, 9)); + case_e.push_back(Edge(1, 4)); + case_e.push_back(Edge(3, 10)); + case_e.push_back(Edge(4, 3)); + case_e.push_back(Edge(5, 0)); + case_e.push_back(Edge(6, 7)); + case_e.push_back(Edge(7, 0)); + case_e.push_back(Edge(7, 2)); + case_e.push_back(Edge(7, 10)); + case_e.push_back(Edge(8, 5)); + case_e.push_back(Edge(9, 12)); + case_e.push_back(Edge(9, 11)); + case_e.push_back(Edge(9, 13)); + case_e.push_back(Edge(10, 1)); + case_e.push_back(Edge(10, 4)); + case_e.push_back(Edge(12, 0)); + case_e.push_back(Edge(11, 12)); + + // detect the subgraph + mas->mod_graph(V, &case_e); + subgraph = mas->find_subgraph(); + if (subgraph != nullptr) { + cout << "subgraph->size(): " << subgraph->size() << endl; + cout << "Ea: "; + for (unsigned i = 0; i < subgraph->size(); i++) { + // print out the subgraph + cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") "; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6 + rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13 + rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1 + rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3 + rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4 + rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7 + rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2 + rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0 + rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8 + rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9 + rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5 + rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12 + rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10 + rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11 + + assert(rs.size() == V); + + output_svg(rs, case_e, "mas_case_e.svg", false, true, subgraph); + for(int i = 0; i < V; i++) { delete rs[i]; } + rs.clear(); + delete subgraph; + } + else { + cout << "No subgraph found" << endl; + } + + // create case F + // case F consists of the same graph with sinks + cout << endl << "ENTERING CASE F" << endl; + V = 3; + case_f.push_back(Edge(0, 1)); + case_f.push_back(Edge(0, 2)); + case_f.push_back(Edge(1, 2)); + + // detect the subgraph + mas->mod_graph(V, &case_f); + subgraph = mas->find_subgraph(); + + if (subgraph != nullptr) { + cout << "subgraph->size(): " << subgraph->size() << endl; + cout << "Ea: "; + for (unsigned i = 0; i < subgraph->size(); i++) { + // print out the subgraph + cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") "; + } + + cout << endl; + + // output a picture + rs.push_back(new Rectangle(10,10+5,10,10+5)); + rs.push_back(new Rectangle(40,40+5,30,30+5)); + rs.push_back(new Rectangle(15,15+5,60,60+5)); + + assert(rs.size() == V); + + output_svg(rs, case_f, "mas_case_f.svg", false, true, subgraph); + for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; } + rs.clear(); + delete subgraph; + } + else { + cout << "No subgraph found" << endl; + } + + // END TEST + delete mas; + + return 0; +} diff --git a/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters01.cpp b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters01.cpp new file mode 100644 index 0000000..6031c71 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters01.cpp @@ -0,0 +1,333 @@ +// Based on debug file from Christoph Daniel Schulze +// cgraph_3_after_layout.svg +#include <vector> +#include <utility> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + EdgeLengths eLengths; + double defaultEdgeLength=50; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + rect = new vpsc::Rectangle(245.517, 247.517, 279.574, 281.574); + rs.push_back(rect); + + rect = new vpsc::Rectangle(222.742, 224.742, 318.708, 320.708); + rs.push_back(rect); + + rect = new vpsc::Rectangle(460.345, 462.345, 716.936, 718.936); + rs.push_back(rect); + + rect = new vpsc::Rectangle(607.846, 609.846, 665.496, 667.496); + rs.push_back(rect); + + rect = new vpsc::Rectangle(640.191, 642.191, 637.391, 639.391); + rs.push_back(rect); + + rect = new vpsc::Rectangle(743.519, 745.519, 865.48, 867.48); + rs.push_back(rect); + + rect = new vpsc::Rectangle(807.112, 809.112, 759.798, 761.798); + rs.push_back(rect); + + rect = new vpsc::Rectangle(807.112, 809.112, 699.132, 701.132); + rs.push_back(rect); + + rect = new vpsc::Rectangle(121.997, 123.997, 221.049, 223.049); + rs.push_back(rect); + + rect = new vpsc::Rectangle(224.354, 226.354, 80, 82); + rs.push_back(rect); + + rect = new vpsc::Rectangle(448.583, 450.583, 517.722, 519.722); + rs.push_back(rect); + + rect = new vpsc::Rectangle(460.345, 462.345, 639.516, 641.516); + rs.push_back(rect); + + rect = new vpsc::Rectangle(607.846, 609.846, 583.991, 585.991); + rs.push_back(rect); + + rect = new vpsc::Rectangle(607.846, 609.846, 684.476, 686.476); + rs.push_back(rect); + + rect = new vpsc::Rectangle(625.623, 627.623, 602.774, 604.774); + rs.push_back(rect); + + rect = new vpsc::Rectangle(289.325, 291.325, 455.243, 457.243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(207.785, 209.785, 222.762, 224.762); + rs.push_back(rect); + + rect = new vpsc::Rectangle(159.658, 161.658, 254.197, 256.197); + rs.push_back(rect); + + rect = new vpsc::Rectangle(650.816, 652.816, 809.48, 811.48); + rs.push_back(rect); + + rect = new vpsc::Rectangle(685.012, 687.012, 795.932, 797.932); + rs.push_back(rect); + + rect = new vpsc::Rectangle(751.112, 753.112, 643.132, 645.132); + rs.push_back(rect); + + rect = new vpsc::Rectangle(751.112, 753.112, 608.903, 610.903); + rs.push_back(rect); + + rect = new vpsc::Rectangle(320.184, 322.184, 377.132, 379.132); + rs.push_back(rect); + + rect = new vpsc::Rectangle(336.233, 338.233, 382.124, 384.124); + rs.push_back(rect); + + rect = new vpsc::Rectangle(153.571, 155.571, 391.657, 393.657); + rs.push_back(rect); + + rect = new vpsc::Rectangle(405.396, 407.396, 745.874, 747.874); + rs.push_back(rect); + + rect = new vpsc::Rectangle(460.345, 462.345, 727.442, 729.442); + rs.push_back(rect); + + rect = new vpsc::Rectangle(551.846, 553.846, 527.991, 529.991); + rs.push_back(rect); + + rect = new vpsc::Rectangle(669.714, 671.714, 583.991, 585.991); + rs.push_back(rect); + + rect = new vpsc::Rectangle(171.168, 221.168, 258.197, 308.197); + rs.push_back(rect); + + rect = new vpsc::Rectangle(110.328, 160.328, 266.708, 316.708); + rs.push_back(rect); + + rect = new vpsc::Rectangle(217.18, 267.18, 109.481, 159.481); + rs.push_back(rect); + + rect = new vpsc::Rectangle(632.075, 682.075, 858.531, 908.531); + rs.push_back(rect); + + rect = new vpsc::Rectangle(689.012, 739.012, 813.48, 863.48); + rs.push_back(rect); + + rect = new vpsc::Rectangle(755.112, 805.112, 647.132, 697.132); + rs.push_back(rect); + + rect = new vpsc::Rectangle(786.403, 836.403, 560.258, 610.258); + rs.push_back(rect); + + rect = new vpsc::Rectangle(261.651, 311.651, 247.06, 297.06); + rs.push_back(rect); + + rect = new vpsc::Rectangle(304.164, 354.164, 322.708, 372.708); + rs.push_back(rect); + + rect = new vpsc::Rectangle(70, 120, 325.132, 375.132); + rs.push_back(rect); + + rect = new vpsc::Rectangle(353.92, 403.92, 770.169, 820.169); + rs.push_back(rect); + + rect = new vpsc::Rectangle(464.345, 514.345, 749.874, 799.874); + rs.push_back(rect); + + rect = new vpsc::Rectangle(555.846, 605.846, 531.991, 581.991); + rs.push_back(rect); + + rect = new vpsc::Rectangle(696.038, 746.038, 531.991, 581.991); + rs.push_back(rect); + + es.push_back(std::make_pair(0, 1)); + es.push_back(std::make_pair(0, 22)); + es.push_back(std::make_pair(1, 23)); + es.push_back(std::make_pair(1, 24)); + es.push_back(std::make_pair(2, 3)); + es.push_back(std::make_pair(2, 25)); + es.push_back(std::make_pair(3, 4)); + es.push_back(std::make_pair(3, 26)); + es.push_back(std::make_pair(3, 27)); + es.push_back(std::make_pair(4, 28)); + es.push_back(std::make_pair(5, 6)); + es.push_back(std::make_pair(5, 18)); + es.push_back(std::make_pair(6, 7)); + es.push_back(std::make_pair(6, 19)); + es.push_back(std::make_pair(6, 20)); + es.push_back(std::make_pair(7, 21)); + es.push_back(std::make_pair(8, 17)); + es.push_back(std::make_pair(9, 31)); + es.push_back(std::make_pair(10, 11)); + es.push_back(std::make_pair(10, 12)); + es.push_back(std::make_pair(10, 13)); + es.push_back(std::make_pair(10, 14)); + es.push_back(std::make_pair(10, 15)); + es.push_back(std::make_pair(10, 22)); + es.push_back(std::make_pair(10, 23)); + es.push_back(std::make_pair(11, 12)); + es.push_back(std::make_pair(11, 25)); + es.push_back(std::make_pair(11, 26)); + es.push_back(std::make_pair(12, 27)); + es.push_back(std::make_pair(12, 28)); + es.push_back(std::make_pair(13, 14)); + es.push_back(std::make_pair(13, 18)); + es.push_back(std::make_pair(13, 19)); + es.push_back(std::make_pair(14, 20)); + es.push_back(std::make_pair(14, 21)); + es.push_back(std::make_pair(15, 24)); + es.push_back(std::make_pair(16, 17)); + es.push_back(std::make_pair(16, 36)); + es.push_back(std::make_pair(17, 29)); + es.push_back(std::make_pair(17, 30)); + es.push_back(std::make_pair(18, 32)); + es.push_back(std::make_pair(19, 33)); + es.push_back(std::make_pair(20, 34)); + es.push_back(std::make_pair(21, 35)); + es.push_back(std::make_pair(22, 36)); + es.push_back(std::make_pair(23, 37)); + es.push_back(std::make_pair(24, 38)); + es.push_back(std::make_pair(25, 39)); + es.push_back(std::make_pair(26, 40)); + es.push_back(std::make_pair(27, 41)); + es.push_back(std::make_pair(28, 42)); + es.push_back(std::make_pair(31, 36)); + es.push_back(std::make_pair(32, 33)); + es.push_back(std::make_pair(34, 35)); + es.push_back(std::make_pair(36, 37)); + es.push_back(std::make_pair(39, 40)); + es.push_back(std::make_pair(41, 42)); + + double padding = 6; + ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths); + alg.setAvoidNodeOverlaps(true); + RootCluster *cluster140389150311456 = new RootCluster(); + cluster140389150311456->addChildNode(0); + cluster140389150311456->addChildNode(1); + cluster140389150311456->addChildNode(2); + cluster140389150311456->addChildNode(3); + cluster140389150311456->addChildNode(4); + cluster140389150311456->addChildNode(5); + cluster140389150311456->addChildNode(6); + cluster140389150311456->addChildNode(7); + cluster140389150311456->addChildNode(8); + cluster140389150311456->addChildNode(9); + cluster140389150311456->addChildNode(10); + cluster140389150311456->addChildNode(11); + cluster140389150311456->addChildNode(12); + cluster140389150311456->addChildNode(13); + cluster140389150311456->addChildNode(14); + cluster140389150311456->addChildNode(15); + cluster140389150311456->addChildNode(16); + cluster140389150311456->addChildNode(17); + cluster140389150311456->addChildNode(18); + cluster140389150311456->addChildNode(19); + cluster140389150311456->addChildNode(20); + cluster140389150311456->addChildNode(21); + cluster140389150311456->addChildNode(22); + cluster140389150311456->addChildNode(23); + cluster140389150311456->addChildNode(24); + cluster140389150311456->addChildNode(25); + cluster140389150311456->addChildNode(26); + cluster140389150311456->addChildNode(27); + cluster140389150311456->addChildNode(28); + RectangularCluster *cluster140389152494880 = new RectangularCluster(); + cluster140389152494880->setPadding(padding); + cluster140389152494880->addChildNode(36); + cluster140389150311456->addChildCluster(cluster140389152494880); + RectangularCluster *cluster140389150048048 = new RectangularCluster(); + cluster140389150048048->setPadding(padding); + cluster140389150048048->addChildNode(38); + cluster140389150048048->addChildNode(37); + cluster140389150311456->addChildCluster(cluster140389150048048); + RectangularCluster *cluster140389150180400 = new RectangularCluster(); + cluster140389150180400->setPadding(padding); + cluster140389150180400->addChildNode(30); + cluster140389150180400->addChildNode(29); + cluster140389150311456->addChildCluster(cluster140389150180400); + RectangularCluster *cluster140389150298288 = new RectangularCluster(); + cluster140389150298288->setPadding(padding); + cluster140389150298288->addChildNode(39); + cluster140389150311456->addChildCluster(cluster140389150298288); + RectangularCluster *cluster140389150179600 = new RectangularCluster(); + cluster140389150179600->setPadding(padding); + cluster140389150179600->addChildNode(41); + cluster140389150179600->addChildNode(40); + cluster140389150311456->addChildCluster(cluster140389150179600); + RectangularCluster *cluster140389150131760 = new RectangularCluster(); + cluster140389150131760->setPadding(padding); + cluster140389150131760->addChildNode(42); + cluster140389150311456->addChildCluster(cluster140389150131760); + RectangularCluster *cluster140389150091712 = new RectangularCluster(); + cluster140389150091712->setPadding(padding); + cluster140389150091712->addChildNode(32); + cluster140389150311456->addChildCluster(cluster140389150091712); + RectangularCluster *cluster140389152581264 = new RectangularCluster(); + cluster140389152581264->setPadding(padding); + cluster140389152581264->addChildNode(34); + cluster140389152581264->addChildNode(33); + cluster140389150311456->addChildCluster(cluster140389152581264); + RectangularCluster *cluster140389144224352 = new RectangularCluster(); + cluster140389144224352->setPadding(padding); + cluster140389144224352->addChildNode(35); + cluster140389150311456->addChildCluster(cluster140389144224352); + RectangularCluster *cluster140389144198304 = new RectangularCluster(); + cluster140389144198304->setPadding(padding); + cluster140389144198304->addChildNode(30); + cluster140389144198304->addChildNode(29); + cluster140389150311456->addChildCluster(cluster140389144198304); + RectangularCluster *cluster140389144177184 = new RectangularCluster(); + cluster140389144177184->setPadding(padding); + cluster140389144177184->addChildNode(31); + cluster140389150311456->addChildCluster(cluster140389144177184); + RectangularCluster *cluster140389144168944 = new RectangularCluster(); + cluster140389144168944->setPadding(padding); + cluster140389144168944->addChildNode(36); + cluster140389144168944->addChildNode(37); + cluster140389150311456->addChildCluster(cluster140389144168944); + RectangularCluster *cluster140389144228288 = new RectangularCluster(); + cluster140389144228288->setPadding(padding); + cluster140389144228288->addChildNode(39); + cluster140389144228288->addChildNode(40); + cluster140389150311456->addChildCluster(cluster140389144228288); + RectangularCluster *cluster140389144244064 = new RectangularCluster(); + cluster140389144228288->setPadding(padding); + cluster140389144244064->addChildNode(42); + cluster140389144244064->addChildNode(41); + cluster140389150311456->addChildCluster(cluster140389144244064); + RectangularCluster *cluster140389144206000 = new RectangularCluster(); + cluster140389144206000->setPadding(padding); + cluster140389144206000->addChildNode(32); + cluster140389144206000->addChildNode(33); + cluster140389150311456->addChildCluster(cluster140389144206000); + RectangularCluster *cluster140389144175920 = new RectangularCluster(); + cluster140389144175920->setPadding(padding); + cluster140389144175920->addChildNode(35); + cluster140389144175920->addChildNode(34); + cluster140389150311456->addChildCluster(cluster140389144175920); + RectangularCluster *cluster140389144214752 = new RectangularCluster(); + cluster140389144214752->setPadding(padding); + cluster140389144214752->addChildNode(38); + cluster140389150311456->addChildCluster(cluster140389144214752); + alg.setClusterHierarchy(cluster140389150311456); + alg.setConstraints(ccs); + + UnsatisfiableConstraintInfos unsatisfiableX, unsatisfiableY; + alg.setUnsatisfiableConstraintInfo(&unsatisfiableX, &unsatisfiableY); + + //alg.makeFeasible(); + alg.run(); + //alg.outputInstanceToSVG("overlappingClusters01"); + + for (size_t i = 0; i < unsatisfiableX.size(); ++i) + { + printf("%s\n", unsatisfiableX[i]->toString().c_str()); + } + for (size_t i = 0; i < unsatisfiableY.size(); ++i) + { + printf("%s\n", unsatisfiableY[i]->toString().c_str()); + } + alg.freeAssociatedObjects(); + return (unsatisfiableX.empty() && unsatisfiableY.empty()) ? 0 : 1; +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters02.cpp b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters02.cpp new file mode 100644 index 0000000..a6bdaf2 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters02.cpp @@ -0,0 +1,100 @@ +// Based on Euler Diagram generation example discussed with Aidan Delaney. +// +// B +// +-----------------------------+ +// A | 2 C | +// +-----------+----------------+ +---+ | +// | | 1 | | 0 | | +// | | | +---+ | +// | 3 +----------------+------------+ +// | | +// | | 4 +// +----------------------------+ +// + +#include <vector> +#include <utility> +#include <cstdlib> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + EdgeLengths eLengths; + double defaultEdgeLength=10; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + double width = 5; + double height = 5; + double pos = 0; + + size_t nodes = 5; + for (size_t i = 0; i < nodes; ++i) + { + rect = new vpsc::Rectangle(pos, pos +width, pos, pos +height); + rs.push_back(rect); + + // XXX randomness is needed because COLA doesn't currently untangle + // the graph properly if all the nodes begin at the same position. + pos += (rand() % 10) - 5; + } + + // Euler dual graph (optional) + es.push_back(std::make_pair(2, 4)); + es.push_back(std::make_pair(3, 4)); + es.push_back(std::make_pair(1, 3)); + es.push_back(std::make_pair(2, 1)); + es.push_back(std::make_pair(2, 0)); + + // Padding around the inside of clusters. + double padding = 3; + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths); + alg.setAvoidNodeOverlaps(true); + RootCluster *rootCluster = new RootCluster(); + + // A contains 1, 3 + RectangularCluster *clusterA = new RectangularCluster(); + clusterA->setPadding(padding); + clusterA->addChildNode(1); + clusterA->addChildNode(3); + + // C contains 0 + RectangularCluster *clusterC = new RectangularCluster(); + clusterC->setPadding(padding); + clusterC->addChildNode(0); + + // B contains 1, 2, C + RectangularCluster *clusterB = new RectangularCluster(); + clusterB->setPadding(padding); + clusterB->addChildNode(1); + clusterB->addChildNode(2); + clusterB->addChildCluster(clusterC); + + // node 4 is in the empty set. + + rootCluster->addChildCluster(clusterA); + rootCluster->addChildCluster(clusterB); + + alg.setConstraints(ccs); + + UnsatisfiableConstraintInfos unsatisfiableX, unsatisfiableY; + alg.setUnsatisfiableConstraintInfo(&unsatisfiableX, &unsatisfiableY); + + alg.setClusterHierarchy(rootCluster); + //alg.makeFeasible(); + alg.run(); + alg.outputInstanceToSVG("overlappingClusters02"); + + for (size_t i = 0; i < unsatisfiableX.size(); ++i) + { + printf("%s\n", unsatisfiableX[i]->toString().c_str()); + } + for (size_t i = 0; i < unsatisfiableY.size(); ++i) + { + printf("%s\n", unsatisfiableY[i]->toString().c_str()); + } + alg.freeAssociatedObjects(); + return (unsatisfiableX.empty() && unsatisfiableY.empty()) ? 0 : 1; +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters04.cpp b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters04.cpp new file mode 100644 index 0000000..45a06ff --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters04.cpp @@ -0,0 +1,61 @@ +// From Aidan Delaney: a_b_ab_abc.json.svg +// Regression test for SEGFAULT caused by specifing an invalid node index 7 +// in cluster description. +#include <vector> +#include <utility> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + EdgeLengths eLengths; + double defaultEdgeLength=10; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + rect = new vpsc::Rectangle(0, 5, 0, 5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-2, 3, -2, 3); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-1, 4, -1, 4); + rs.push_back(rect); + + rect = new vpsc::Rectangle(1, 6, 1, 6); + rs.push_back(rect); + + rect = new vpsc::Rectangle(1, 6, 1, 6); + rs.push_back(rect); + + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths); + alg.setAvoidNodeOverlaps(true); + + RootCluster *cluster33771480 = new RootCluster(); + RectangularCluster *cluster33771952 = new RectangularCluster(); + cluster33771952->setPadding(Box(2)); + cluster33771952->addChildNode(1); + cluster33771952->addChildNode(3); + cluster33771952->addChildNode(7); + cluster33771480->addChildCluster(cluster33771952); + + RectangularCluster *cluster33772496 = new RectangularCluster(); + cluster33772496->setPadding(Box(2)); + cluster33772496->addChildNode(2); + cluster33772496->addChildNode(3); + cluster33772496->addChildNode(7); + cluster33771480->addChildCluster(cluster33772496); + + RectangularCluster *cluster33773040 = new RectangularCluster(); + cluster33773040->setPadding(Box(2)); + cluster33773040->addChildNode(7); + cluster33771480->addChildCluster(cluster33773040); + + alg.setClusterHierarchy(cluster33771480); + + alg.setConstraints(ccs); + alg.makeFeasible(); + //alg.outputInstanceToSVG("overlappingCLusters04"); + alg.freeAssociatedObjects(); +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/page_bounds.cpp b/src/3rdparty/adaptagrams/libcola/tests/page_bounds.cpp new file mode 100644 index 0000000..b753cbf --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/page_bounds.cpp @@ -0,0 +1,102 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** + * \file page_bounds.cpp + * + * test/example showing the use of page boundary constraints + */ +#include<iostream> +#include<vector> +#include <cmath> +#include <time.h> +#include <valarray> + +#include "graphlayouttest.h" + +vector<Edge> random_graph(unsigned n) { + vector<Edge> edges; + for(unsigned i=1;i<n;i++) { + edges.push_back(make_pair(i-1,i)); + } + for(unsigned i=0;i<n;i++) { + for(unsigned j=i+1;j<n;j++) { + double r=(double)rand()/(double)RAND_MAX; + if(r < 1./(double)n) { + edges.push_back(make_pair(i,j)); + } + } + } + + return edges; +} +int main() { + unsigned V=30; + CompoundConstraints ccs; + vector<Edge> es = random_graph(V); + double defaultEdgeLength=40; + cola::PageBoundaryConstraints* pbc = + new cola::PageBoundaryConstraints(0,200,0,200,100); + + double w=2.0, h=2.0; + for(unsigned i=0;i<V;i++) { + pbc->addShape(i, w/2, h/2); + } + ccs.push_back(pbc); + + cout << "V="<<V<<endl; + double width=1000; + double height=1000; + //srand(time(nullptr)); + vector<pair<double,double> > startpos(V); + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + startpos[i]=make_pair(x,y); + } + + /*void run_test( + vector<pair<double,double> > const &startpos, + vector<Edge> const &es, + const double defaultEdgeLength, + CompoundConstraints &cx, + CompoundConstraints &cy, + const SolverType s, + const bool constrained, + const char *fname, + const char *testdesc) { + */ + +/* + run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,"random","cg"); + run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,"random", "ip"); + run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,"random", "ugp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,"random", "sgp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,"random", "cip"); + run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,"random", "csgp"); + */ + run_test(startpos,es,defaultEdgeLength,ccs,UGP,true,"random", "cugp"); + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/planar.cpp b/src/3rdparty/adaptagrams/libcola/tests/planar.cpp new file mode 100644 index 0000000..f5eae9c --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/planar.cpp @@ -0,0 +1,287 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file topology.cpp + * + * tests topology preserving layout. graph is a triangle. + * We have a fourth disconnected node starting inside the triangle. + * We give the disconnected node a desired position outside the triangle + * and begin layout. Layout should converge to near zero stress as all + * edges should be able to reach their desired lengths, and disconnected + * node should still be inside the triangle at the end. + */ +/* +* Authors: +* Tim Dwyer <tgdwyer@gmail.com> +*/ +#include <iostream> +#include <iomanip> +#include <fstream> + +#include <vector> +#include <valarray> +#include <algorithm> +#include <float.h> +#include <libcola/cola.h> +#include <libtopology/topology_graph.h> +#include "graphlayouttest.h" +using namespace std; +using namespace cola; + +struct TestCase { + topology::Nodes vs; + topology::Edges tes; + topology::EdgePoints ps; + vector<vpsc::Rectangle*> rs; + vector<Edge> es; + void addNode(double minX, double minY, double w, double h) { + vpsc::Rectangle* r = new Rectangle(minX, minX+w, minY, minY+h); + rs.push_back(r); + topology::Node *v = new topology::Node(vs.size(), r); + vs.push_back(v); + } + void addToPath(unsigned vID, topology::EdgePoint::RectIntersect i) { + ps.push_back(new topology::EdgePoint(vs[vID],i)); + } + void addEdge(double l) { + tes.push_back(new topology::Edge(l, ps)); + es.push_back(make_pair(ps[0]->node->id,ps[ps.size()-1]->node->id)); + ps.clear(); + } + ~TestCase() { + for_each(rs.begin(),rs.end(),delete_object()); + for_each(tes.begin(),tes.end(),delete_object()); + for_each(vs.begin(),vs.end(),delete_object()); + } +}; +void writeFile(const topology::Nodes& vs, const topology::Edges& es, const char *outputFileName) { + const unsigned n=vs.size(); + vector<cola::Edge> cedges; + + for(unsigned i=0;i<es.size();i++) { + cedges.push_back(make_pair(1,2)); + } + + vector<straightener::Route*> routes; + for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) { + routes.push_back((*e)->getRoute()); + } + + vector<string> labels(n); + for(unsigned i=0;i<n;++i) { + stringstream ss; + ss << i; + labels[i]=ss.str(); + } + + vector<vpsc::Rectangle*> rs; + for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) { + rs.push_back((*i)->rect); + } + OutputFile of(rs,cedges,nullptr,outputFileName,true,false); + of.setLabels(labels); + of.routes=&routes; + of.generate(); + + for_each(routes.begin(),routes.end(),delete_object()); +} +struct Test : TestConvergence { + Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es) : TestConvergence(d,i), vs(vs), es(es) {} + bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) { + cout << "stress="<<new_stress<<" iteration="<<iterations<<endl; + stringstream ss; + ss << "planar-" << setfill('0') << setw(3) << ++iterations << ".svg"; + writeFile(vs,es,ss.str().c_str()); + if(iterations<100) { + return false; + } + return true; + return TestConvergence::operator()(new_stress,X,Y); + } + double lastStress; + topology::Nodes& vs; + topology::Edges& es; +}; +void test() { + TestCase t; +t.addNode(144.000000,511.000000,8.000000,8.000000); +t.addNode(413.000000,155.000000,8.000000,8.000000); +t.addNode(437.000000,169.000000,8.000000,8.000000); +t.addNode(436.000000,122.000000,8.000000,8.000000); +t.addNode(460.000000,150.000000,8.000000,8.000000); +t.addNode(466.000000,178.000000,8.000000,8.000000); +t.addNode(469.000000,198.000000,8.000000,8.000000); +t.addNode(378.000000,332.000000,8.000000,8.000000); +t.addNode(368.000000,315.000000,8.000000,8.000000); +t.addNode(332.000000,341.000000,8.000000,8.000000); +t.addNode(282.000000,374.000000,8.000000,8.000000); +t.addNode(329.000000,364.000000,8.000000,8.000000); +t.addNode(346.000000,390.000000,8.000000,8.000000); +t.addNode(375.000000,402.000000,8.000000,8.000000); +t.addNode(357.000000,438.000000,8.000000,8.000000); +t.addNode(382.000000,422.000000,8.000000,8.000000); +t.addNode(453.000000,280.000000,8.000000,8.000000); +t.addNode(452.000000,258.000000,8.000000,8.000000); +t.addNode(530.000000,449.000000,8.000000,8.000000); +t.addNode(576.000000,431.000000,8.000000,8.000000); +t.addNode(577.000000,408.000000,8.000000,8.000000); +t.addNode(606.000000,438.000000,8.000000,8.000000); +t.addNode(624.000000,467.000000,8.000000,8.000000); +t.addNode(620.000000,492.000000,8.000000,8.000000); +t.addNode(681.000000,492.000000,8.000000,8.000000); +t.addNode(729.000000,528.000000,8.000000,8.000000); +t.addNode(765.000000,515.000000,8.000000,8.000000); +t.addNode(765.000000,492.000000,8.000000,8.000000); +t.addNode(858.000000,538.000000,8.000000,8.000000); +t.addNode(2.000000,544.000000,8.000000,8.000000); +t.addToPath(28,(topology::EdgePoint::RectIntersect)4); +t.addToPath(27,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(28,(topology::EdgePoint::RectIntersect)4); +t.addToPath(26,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(25,(topology::EdgePoint::RectIntersect)4); +t.addToPath(28,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(25,(topology::EdgePoint::RectIntersect)4); +t.addToPath(29,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(17,(topology::EdgePoint::RectIntersect)4); +t.addToPath(24,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(16,(topology::EdgePoint::RectIntersect)4); +//t.addToPath(20,(topology::EdgePoint::RectIntersect)1); +t.addToPath(24,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(16,(topology::EdgePoint::RectIntersect)4); +t.addToPath(7,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(24,(topology::EdgePoint::RectIntersect)4); +t.addToPath(25,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(22,(topology::EdgePoint::RectIntersect)4); +t.addToPath(24,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(22,(topology::EdgePoint::RectIntersect)4); +t.addToPath(0,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(22,(topology::EdgePoint::RectIntersect)4); +t.addToPath(23,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(22,(topology::EdgePoint::RectIntersect)4); +t.addToPath(18,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(21,(topology::EdgePoint::RectIntersect)4); +t.addToPath(20,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(20,(topology::EdgePoint::RectIntersect)4); +t.addToPath(19,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(18,(topology::EdgePoint::RectIntersect)4); +t.addToPath(20,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(18,(topology::EdgePoint::RectIntersect)4); +t.addToPath(16,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(14,(topology::EdgePoint::RectIntersect)4); +t.addToPath(18,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(13,(topology::EdgePoint::RectIntersect)4); +t.addToPath(14,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(15,(topology::EdgePoint::RectIntersect)4); +t.addToPath(14,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(12,(topology::EdgePoint::RectIntersect)4); +t.addToPath(13,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(12,(topology::EdgePoint::RectIntersect)4); +t.addToPath(10,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(11,(topology::EdgePoint::RectIntersect)4); +t.addToPath(12,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(10,(topology::EdgePoint::RectIntersect)4); +t.addToPath(11,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(9,(topology::EdgePoint::RectIntersect)4); +t.addToPath(13,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(9,(topology::EdgePoint::RectIntersect)4); +t.addToPath(10,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(6,(topology::EdgePoint::RectIntersect)4); +//t.addToPath(8,(topology::EdgePoint::RectIntersect)2); +t.addToPath(9,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(6,(topology::EdgePoint::RectIntersect)4); +t.addToPath(7,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(8,(topology::EdgePoint::RectIntersect)4); +t.addToPath(7,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(6,(topology::EdgePoint::RectIntersect)4); +t.addToPath(25,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(5,(topology::EdgePoint::RectIntersect)4); +t.addToPath(10,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(5,(topology::EdgePoint::RectIntersect)4); +t.addToPath(29,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(29,(topology::EdgePoint::RectIntersect)4); +t.addToPath(1,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(3,(topology::EdgePoint::RectIntersect)4); +t.addToPath(2,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(5,(topology::EdgePoint::RectIntersect)4); +t.addToPath(6,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(4,(topology::EdgePoint::RectIntersect)4); +t.addToPath(5,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(3,(topology::EdgePoint::RectIntersect)4); +t.addToPath(4,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); +t.addToPath(29,(topology::EdgePoint::RectIntersect)4); +//t.addToPath(1,(topology::EdgePoint::RectIntersect)2); +t.addToPath(3,(topology::EdgePoint::RectIntersect)4); +t.addEdge(70.000000); + writeFile(t.vs,t.tes,"planar-000.svg"); + Test test(0.00001,100,t.vs,t.tes); + ConstrainedFDLayout alg(t.rs,t.es,70.0,nullptr,test,nullptr); + alg.setTopology(&t.vs,&t.tes); + alg.run(true,true); + double finalStress=alg.computeStress(); + printf("finalStress=%f\n",finalStress); + + //assert(finalStress<1e-5); +} +int main() { + test(); + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/random_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/random_graph.cpp new file mode 100644 index 0000000..68e2ee1 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/random_graph.cpp @@ -0,0 +1,113 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include<iostream> +#include<vector> +#include <cmath> +#include <time.h> +#include <valarray> + +#include "graphlayouttest.h" + +vector<Edge> random_graph(unsigned n) { + vector<Edge> edges; + for(unsigned i=1;i<n;i++) { + edges.push_back(make_pair(i-1,i)); + } + for(unsigned i=0;i<n;i++) { + for(unsigned j=i+1;j<n;j++) { + double r=(double)rand()/(double)RAND_MAX; + if(r < 1./(double)n) { + edges.push_back(make_pair(i,j)); + } + } + } + + return edges; +} +int main() { + unsigned V=100; + CompoundConstraints ccs; + vector<Edge> es = random_graph(V); + double defaultEdgeLength=40; + for(unsigned i=0;i<es.size();i++) { + unsigned start=es[i].first, end=es[i].second; + ccs.push_back( + new SeparationConstraint(vpsc::YDIM, start,end,-10)); + } + + cout << "V="<<V<<endl; + double width=1000; + double height=1000; + //srand(time(nullptr)); + vector<pair<double,double> > startpos(V); + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + startpos[i]=make_pair(x,y); + } + + /*void run_test( + vector<pair<double,double> > const &startpos, + vector<Edge> const &es, + const double defaultEdgeLength, + CompoundConstraints &cx, + CompoundConstraints &cy, + const SolverType s, + const bool constrained, + const char *fname, + const char *testdesc) { + */ + +/* + run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,"random","cg"); + run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,"random", "ip"); + run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,"random", "ugp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,"random", "sgp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,"random", "cip"); + run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,"random", "cugp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,"random", "csgp"); + */ + vector<vpsc::Rectangle*> rs; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5)); + } + CheckProgress test(0.0001,200); + ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength, + StandardEdgeLengths,&test); + //alg.setYConstraints(&cy); + alg.run(); + ConstrainedFDLayout alg2(rs,es,defaultEdgeLength, + StandardEdgeLengths, &test); + //alg2.setYConstraints(&cy); + alg2.run(); + OutputFile output(rs,es,nullptr,"random.pdf"); + output.generate(); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/rectangularClusters01.cpp b/src/3rdparty/adaptagrams/libcola/tests/rectangularClusters01.cpp new file mode 100644 index 0000000..4269b3b --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/rectangularClusters01.cpp @@ -0,0 +1,1135 @@ +#include <vector>
+#include <utility>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ EdgeLengths eLengths;
+ double defaultEdgeLength=1;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(56.4457, 117.446, 954.77, 1043.77);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(119.446, 127.446, 992.02, 1000.02);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(119.446, 127.446, 1004.27, 1012.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(119.446, 127.446, 1016.52, 1024.52);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(46.4457, 54.4457, 1004.27, 1012.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2165.45, 2239.45, 976.562, 1065.56);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2155.45, 2163.45, 1026.06, 1034.06);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-106.554, 6.44565, 955.683, 1044.68);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(8.44565, 16.4457, 1005.18, 1013.18);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(331.446, 412.446, 1015.55, 1104.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(414.446, 422.446, 1065.05, 1073.05);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(356.112, 364.112, 1106.55, 1114.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(339.779, 347.779, 1106.55, 1114.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(321.446, 329.446, 1073.22, 1081.22);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(321.446, 329.446, 1056.88, 1064.88);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(477.446, 559.446, 948.569, 1037.57);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(561.446, 569.446, 998.069, 1006.07);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(503.946, 511.946, 1039.57, 1047.57);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(467.446, 475.446, 998.069, 1006.07);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(56.4457, 127.446, 863.77, 952.77);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(129.446, 137.446, 913.27, 921.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(46.4457, 54.4457, 913.27, 921.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(177.446, 281.446, 922.444, 1011.44);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(283.446, 291.446, 971.944, 979.944);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 986.644, 994.644);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 976.844, 984.844);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 967.044, 975.044);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 957.244, 965.244);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(331.446, 427.446, 924.551, 1013.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(429.446, 437.446, 974.051, 982.051);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(321.446, 329.446, 974.051, 982.051);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(609.446, 730.446, 936.692, 1025.69);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 971.492, 979.492);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 981.292, 989.292);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 991.092, 999.092);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 1000.89, 1008.89);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(599.446, 607.446, 986.192, 994.192);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(780.446, 846.446, 838.172, 932.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(848.446, 856.446, 890.172, 898.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(770.446, 778.446, 890.172, 898.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(780.446, 846.446, 934.172, 1028.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(848.446, 856.446, 986.172, 994.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(770.446, 778.446, 986.172, 994.172);
+ rs.push_back(rect);
+
+ // rect-43
+ rect = new vpsc::Rectangle(941.446, 1155.45, 922.958, 1025.96);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1147.45, 1155.45, 979.458, 987.458);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 998.358, 1006.36);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 985.757, 993.757);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 973.158, 981.158);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 960.558, 968.558);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(780.446, 846.446, 1030.17, 1124.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(848.446, 856.446, 1082.17, 1090.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(770.446, 778.446, 1082.17, 1090.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1195.45, 1263.45, 938.653, 1017.65);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1265.45, 1273.45, 983.153, 991.153);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1185.45, 1193.45, 989.653, 997.653);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1185.45, 1193.45, 976.653, 984.653);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1313.45, 1374.45, 934.988, 1013.99);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1376.45, 1384.45, 979.488, 987.488);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1303.45, 1311.45, 979.488, 987.488);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1586.45, 1660.45, 855.704, 944.704);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1576.45, 1584.45, 905.204, 913.204);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1424.45, 1536.45, 866.456, 945.456);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1538.45, 1546.45, 910.956, 918.956);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1414.45, 1422.45, 910.956, 918.956);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1445.45, 1515.45, 947.456, 1036.46);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1517.45, 1525.45, 996.956, 1004.96);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1471.95, 1479.95, 1038.46, 1046.46);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1435.45, 1443.45, 996.956, 1004.96);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1699.45, 1748.45, 970.163, 1059.16);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1750.45, 1758.45, 1019.66, 1027.66);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1689.45, 1697.45, 1027.83, 1035.83);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1689.45, 1697.45, 1011.5, 1019.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1811.45, 1898.45, 1010.04, 1099.04);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1900.45, 1908.45, 1059.54, 1067.54);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1801.45, 1809.45, 1067.7, 1075.7);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1801.45, 1809.45, 1051.37, 1059.37);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1699.45, 1761.45, 1061.16, 1134.16);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1763.45, 1771.45, 1102.66, 1110.66);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1689.45, 1697.45, 1102.66, 1110.66);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2053.45, 2115.45, 985.999, 1080);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2117.45, 2125.45, 1038, 1046);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2080.11, 2088.11, 1082, 1090);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2062.78, 2070.78, 1082, 1090);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2043.45, 2051.45, 1038, 1046);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1948.45, 2003.45, 996.147, 1090.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2005.45, 2013.45, 1048.15, 1056.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1975.11, 1983.11, 1092.15, 1100.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1957.78, 1965.78, 1092.15, 1100.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1938.45, 1946.45, 1048.15, 1056.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1565.45, 1649.45, 951.936, 1040.94);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1651.45, 1659.45, 1001.44, 1009.44);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1555.45, 1563.45, 1001.44, 1009.44);
+ rs.push_back(rect);
+
+ es.push_back(std::make_pair(0, 1));
+ es.push_back(std::make_pair(0, 2));
+ es.push_back(std::make_pair(0, 3));
+ es.push_back(std::make_pair(0, 4));
+ es.push_back(std::make_pair(1, 26));
+ es.push_back(std::make_pair(2, 25));
+ es.push_back(std::make_pair(3, 6));
+ es.push_back(std::make_pair(3, 24));
+ es.push_back(std::make_pair(4, 8));
+ es.push_back(std::make_pair(5, 6));
+ es.push_back(std::make_pair(6, 80));
+ es.push_back(std::make_pair(7, 8));
+ es.push_back(std::make_pair(9, 10));
+ es.push_back(std::make_pair(9, 11));
+ es.push_back(std::make_pair(9, 12));
+ es.push_back(std::make_pair(9, 13));
+ es.push_back(std::make_pair(9, 14));
+ es.push_back(std::make_pair(10, 17));
+ es.push_back(std::make_pair(15, 16));
+ es.push_back(std::make_pair(15, 17));
+ es.push_back(std::make_pair(15, 18));
+ es.push_back(std::make_pair(16, 36));
+ es.push_back(std::make_pair(16, 67));
+ es.push_back(std::make_pair(18, 29));
+ es.push_back(std::make_pair(19, 20));
+ es.push_back(std::make_pair(19, 21));
+ es.push_back(std::make_pair(20, 27));
+ es.push_back(std::make_pair(22, 23));
+ es.push_back(std::make_pair(22, 24));
+ es.push_back(std::make_pair(22, 25));
+ es.push_back(std::make_pair(22, 26));
+ es.push_back(std::make_pair(22, 27));
+ es.push_back(std::make_pair(23, 30));
+ es.push_back(std::make_pair(28, 29));
+ es.push_back(std::make_pair(28, 30));
+ es.push_back(std::make_pair(31, 32));
+ es.push_back(std::make_pair(31, 33));
+ es.push_back(std::make_pair(31, 34));
+ es.push_back(std::make_pair(31, 35));
+ es.push_back(std::make_pair(31, 36));
+ es.push_back(std::make_pair(32, 39));
+ es.push_back(std::make_pair(32, 48));
+ es.push_back(std::make_pair(34, 42));
+ es.push_back(std::make_pair(35, 51));
+ es.push_back(std::make_pair(35, 54));
+ es.push_back(std::make_pair(37, 38));
+ es.push_back(std::make_pair(37, 39));
+ es.push_back(std::make_pair(38, 47));
+ es.push_back(std::make_pair(40, 41));
+ es.push_back(std::make_pair(40, 42));
+ es.push_back(std::make_pair(41, 46));
+ es.push_back(std::make_pair(43, 44));
+ es.push_back(std::make_pair(43, 45));
+ es.push_back(std::make_pair(43, 46));
+ es.push_back(std::make_pair(43, 47));
+ es.push_back(std::make_pair(43, 48));
+ es.push_back(std::make_pair(44, 55));
+ es.push_back(std::make_pair(45, 50));
+ es.push_back(std::make_pair(49, 50));
+ es.push_back(std::make_pair(49, 51));
+ es.push_back(std::make_pair(52, 53));
+ es.push_back(std::make_pair(52, 54));
+ es.push_back(std::make_pair(52, 55));
+ es.push_back(std::make_pair(53, 58));
+ es.push_back(std::make_pair(56, 57));
+ es.push_back(std::make_pair(56, 58));
+ es.push_back(std::make_pair(57, 63));
+ es.push_back(std::make_pair(57, 66));
+ es.push_back(std::make_pair(59, 60));
+ es.push_back(std::make_pair(60, 62));
+ es.push_back(std::make_pair(61, 62));
+ es.push_back(std::make_pair(61, 63));
+ es.push_back(std::make_pair(64, 65));
+ es.push_back(std::make_pair(64, 66));
+ es.push_back(std::make_pair(64, 67));
+ es.push_back(std::make_pair(65, 91));
+ es.push_back(std::make_pair(68, 69));
+ es.push_back(std::make_pair(68, 70));
+ es.push_back(std::make_pair(68, 71));
+ es.push_back(std::make_pair(69, 75));
+ es.push_back(std::make_pair(70, 85));
+ es.push_back(std::make_pair(71, 90));
+ es.push_back(std::make_pair(72, 73));
+ es.push_back(std::make_pair(72, 74));
+ es.push_back(std::make_pair(72, 75));
+ es.push_back(std::make_pair(73, 88));
+ es.push_back(std::make_pair(75, 77));
+ es.push_back(std::make_pair(76, 77));
+ es.push_back(std::make_pair(76, 78));
+ es.push_back(std::make_pair(79, 80));
+ es.push_back(std::make_pair(79, 81));
+ es.push_back(std::make_pair(79, 82));
+ es.push_back(std::make_pair(79, 83));
+ es.push_back(std::make_pair(83, 85));
+ es.push_back(std::make_pair(84, 85));
+ es.push_back(std::make_pair(84, 86));
+ es.push_back(std::make_pair(84, 87));
+ es.push_back(std::make_pair(84, 88));
+ es.push_back(std::make_pair(89, 90));
+ es.push_back(std::make_pair(89, 91));
+
+ eLengths.resize(100);
+ eLengths[0] = 59.6059;
+ eLengths[1] = 59.6059;
+ eLengths[2] = 59.6059;
+ eLengths[3] = 59.6059;
+ eLengths[4] = 63.5296;
+ eLengths[5] = 77.5769;
+ eLengths[6] = 65.8274;
+ eLengths[7] = 65.8274;
+ eLengths[8] = 65.8274;
+ eLengths[9] = 65.8274;
+ eLengths[10] = 65.8274;
+ eLengths[11] = 66.1651;
+ eLengths[12] = 66.1651;
+ eLengths[13] = 66.1651;
+ eLengths[14] = 62.5822;
+ eLengths[15] = 62.5822;
+ eLengths[16] = 74.0984;
+ eLengths[17] = 74.0984;
+ eLengths[18] = 74.0984;
+ eLengths[19] = 74.0984;
+ eLengths[20] = 74.0984;
+ eLengths[21] = 71.111;
+ eLengths[22] = 71.111;
+ eLengths[23] = 80.7601;
+ eLengths[24] = 80.7601;
+ eLengths[25] = 80.7601;
+ eLengths[26] = 80.7601;
+ eLengths[27] = 80.7601;
+ eLengths[28] = 63.0851;
+ eLengths[29] = 63.0851;
+ eLengths[30] = 63.0851;
+ eLengths[31] = 63.0851;
+ eLengths[32] = 115.481;
+ eLengths[33] = 115.481;
+ eLengths[34] = 115.481;
+ eLengths[35] = 115.481;
+ eLengths[36] = 115.481;
+ eLengths[37] = 63.0851;
+ eLengths[38] = 63.0851;
+ eLengths[39] = 57.7745;
+ eLengths[40] = 57.7745;
+ eLengths[41] = 57.7745;
+ eLengths[42] = 55.5618;
+ eLengths[43] = 55.5618;
+ eLengths[44] = 63.5296;
+ eLengths[45] = 74.186;
+ eLengths[46] = 74.186;
+ eLengths[47] = 62.2718;
+ eLengths[48] = 62.2718;
+ eLengths[49] = 62.2718;
+ eLengths[50] = 56.4555;
+ eLengths[51] = 56.4555;
+ eLengths[52] = 56.4555;
+ eLengths[53] = 67.8863;
+ eLengths[54] = 67.8863;
+ eLengths[55] = 67.8863;
+ eLengths[56] = 53.5447;
+ eLengths[57] = 53.5447;
+ eLengths[58] = 61.9596;
+ eLengths[59] = 61.9596;
+ eLengths[60] = 61.9596;
+ eLengths[61] = 61.9596;
+ eLengths[62] = 60.111;
+ eLengths[63] = 60.111;
+ eLengths[64] = 60.111;
+ eLengths[65] = 60.111;
+ eLengths[66] = 66.8471;
+ eLengths[67] = 66.8471;
+ eLengths[68] = 18.3712;
+ eLengths[69] = 18.3712;
+ eLengths[70] = 18.3712;
+ eLengths[71] = 18.3712;
+ eLengths[72] = 10.6066;
+ eLengths[73] = 10.6066;
+ eLengths[74] = 15;
+ eLengths[75] = 15;
+ eLengths[76] = 15;
+ eLengths[77] = 10.6066;
+ eLengths[78] = 10.6066;
+ eLengths[79] = 23.7171;
+ eLengths[80] = 30;
+ eLengths[81] = 23.7171;
+ eLengths[82] = 23.7171;
+ eLengths[83] = 25.9808;
+ eLengths[84] = 21.2132;
+ eLengths[85] = 21.2132;
+ eLengths[86] = 15;
+ eLengths[87] = 21.2132;
+ eLengths[88] = 10.6066;
+ eLengths[89] = 15;
+ eLengths[90] = 15;
+ eLengths[91] = 10.6066;
+ eLengths[92] = 10.6066;
+ eLengths[93] = 15;
+ eLengths[94] = 10.6066;
+ eLengths[95] = 15;
+ eLengths[96] = 15;
+ eLengths[97] = 15;
+ eLengths[98] = 18.3712;
+ eLengths[99] = 15;
+
+ SeparationConstraint *separation479625808 = new SeparationConstraint(vpsc::XDIM, 0, 1, 36.5, true);
+ ccs.push_back(separation479625808);
+
+ SeparationConstraint *separation479626000 = new SeparationConstraint(vpsc::YDIM, 0, 1, -3.25, true);
+ ccs.push_back(separation479626000);
+
+ SeparationConstraint *separation479625936 = new SeparationConstraint(vpsc::XDIM, 0, 2, 36.5, true);
+ ccs.push_back(separation479625936);
+
+ SeparationConstraint *separation479626128 = new SeparationConstraint(vpsc::YDIM, 0, 2, 9, true);
+ ccs.push_back(separation479626128);
+
+ SeparationConstraint *separation479626064 = new SeparationConstraint(vpsc::XDIM, 0, 3, 36.5, true);
+ ccs.push_back(separation479626064);
+
+ SeparationConstraint *separation479626256 = new SeparationConstraint(vpsc::YDIM, 0, 3, 21.25, true);
+ ccs.push_back(separation479626256);
+
+ SeparationConstraint *separation479626192 = new SeparationConstraint(vpsc::XDIM, 0, 4, -36.5, true);
+ ccs.push_back(separation479626192);
+
+ SeparationConstraint *separation479626384 = new SeparationConstraint(vpsc::YDIM, 0, 4, 9, true);
+ ccs.push_back(separation479626384);
+
+ SeparationConstraint *separation479626320 = new SeparationConstraint(vpsc::XDIM, 5, 6, -43, true);
+ ccs.push_back(separation479626320);
+
+ SeparationConstraint *separation479626512 = new SeparationConstraint(vpsc::YDIM, 5, 6, 9, true);
+ ccs.push_back(separation479626512);
+
+ SeparationConstraint *separation479626448 = new SeparationConstraint(vpsc::XDIM, 7, 8, 62.5, true);
+ ccs.push_back(separation479626448);
+
+ SeparationConstraint *separation479626640 = new SeparationConstraint(vpsc::YDIM, 7, 8, 9, true);
+ ccs.push_back(separation479626640);
+
+ SeparationConstraint *separation479626576 = new SeparationConstraint(vpsc::XDIM, 9, 10, 46.5, true);
+ ccs.push_back(separation479626576);
+
+ SeparationConstraint *separation479626768 = new SeparationConstraint(vpsc::YDIM, 9, 10, 9, true);
+ ccs.push_back(separation479626768);
+
+ SeparationConstraint *separation479626704 = new SeparationConstraint(vpsc::XDIM, 9, 11, -11.8333, true);
+ ccs.push_back(separation479626704);
+
+ SeparationConstraint *separation479626896 = new SeparationConstraint(vpsc::YDIM, 9, 11, 50.5, true);
+ ccs.push_back(separation479626896);
+
+ SeparationConstraint *separation479626832 = new SeparationConstraint(vpsc::XDIM, 9, 12, -28.1667, true);
+ ccs.push_back(separation479626832);
+
+ SeparationConstraint *separation479627024 = new SeparationConstraint(vpsc::YDIM, 9, 12, 50.5, true);
+ ccs.push_back(separation479627024);
+
+ SeparationConstraint *separation479626960 = new SeparationConstraint(vpsc::XDIM, 9, 13, -46.5, true);
+ ccs.push_back(separation479626960);
+
+ SeparationConstraint *separation479627152 = new SeparationConstraint(vpsc::YDIM, 9, 13, 17.1667, true);
+ ccs.push_back(separation479627152);
+
+ SeparationConstraint *separation479627088 = new SeparationConstraint(vpsc::XDIM, 9, 14, -46.5, true);
+ ccs.push_back(separation479627088);
+
+ SeparationConstraint *separation479627280 = new SeparationConstraint(vpsc::YDIM, 9, 14, 0.833333, true);
+ ccs.push_back(separation479627280);
+
+ SeparationConstraint *separation479627216 = new SeparationConstraint(vpsc::XDIM, 15, 16, 47, true);
+ ccs.push_back(separation479627216);
+
+ SeparationConstraint *separation479627408 = new SeparationConstraint(vpsc::YDIM, 15, 16, 9, true);
+ ccs.push_back(separation479627408);
+
+ SeparationConstraint *separation479627344 = new SeparationConstraint(vpsc::XDIM, 15, 17, -10.5, true);
+ ccs.push_back(separation479627344);
+
+ SeparationConstraint *separation479627536 = new SeparationConstraint(vpsc::YDIM, 15, 17, 50.5, true);
+ ccs.push_back(separation479627536);
+
+ SeparationConstraint *separation479627472 = new SeparationConstraint(vpsc::XDIM, 15, 18, -47, true);
+ ccs.push_back(separation479627472);
+
+ SeparationConstraint *separation479627664 = new SeparationConstraint(vpsc::YDIM, 15, 18, 9, true);
+ ccs.push_back(separation479627664);
+
+ SeparationConstraint *separation479627600 = new SeparationConstraint(vpsc::XDIM, 19, 20, 41.5, true);
+ ccs.push_back(separation479627600);
+
+ SeparationConstraint *separation479627792 = new SeparationConstraint(vpsc::YDIM, 19, 20, 9, true);
+ ccs.push_back(separation479627792);
+
+ SeparationConstraint *separation479627728 = new SeparationConstraint(vpsc::XDIM, 19, 21, -41.5, true);
+ ccs.push_back(separation479627728);
+
+ SeparationConstraint *separation479627920 = new SeparationConstraint(vpsc::YDIM, 19, 21, 9, true);
+ ccs.push_back(separation479627920);
+
+ SeparationConstraint *separation479627856 = new SeparationConstraint(vpsc::XDIM, 22, 23, 58, true);
+ ccs.push_back(separation479627856);
+
+ SeparationConstraint *separation479628048 = new SeparationConstraint(vpsc::YDIM, 22, 23, 9, true);
+ ccs.push_back(separation479628048);
+
+ SeparationConstraint *separation479627984 = new SeparationConstraint(vpsc::XDIM, 22, 24, -58, true);
+ ccs.push_back(separation479627984);
+
+ SeparationConstraint *separation479628176 = new SeparationConstraint(vpsc::YDIM, 22, 24, 23.7, true);
+ ccs.push_back(separation479628176);
+
+ SeparationConstraint *separation479628112 = new SeparationConstraint(vpsc::XDIM, 22, 25, -58, true);
+ ccs.push_back(separation479628112);
+
+ SeparationConstraint *separation479628304 = new SeparationConstraint(vpsc::YDIM, 22, 25, 13.9, true);
+ ccs.push_back(separation479628304);
+
+ SeparationConstraint *separation479628240 = new SeparationConstraint(vpsc::XDIM, 22, 26, -58, true);
+ ccs.push_back(separation479628240);
+
+ SeparationConstraint *separation479628432 = new SeparationConstraint(vpsc::YDIM, 22, 26, 4.1, true);
+ ccs.push_back(separation479628432);
+
+ SeparationConstraint *separation479628368 = new SeparationConstraint(vpsc::XDIM, 22, 27, -58, true);
+ ccs.push_back(separation479628368);
+
+ SeparationConstraint *separation479628560 = new SeparationConstraint(vpsc::YDIM, 22, 27, -5.7, true);
+ ccs.push_back(separation479628560);
+
+ SeparationConstraint *separation479628496 = new SeparationConstraint(vpsc::XDIM, 28, 29, 54, true);
+ ccs.push_back(separation479628496);
+
+ SeparationConstraint *separation479628688 = new SeparationConstraint(vpsc::YDIM, 28, 29, 9, true);
+ ccs.push_back(separation479628688);
+
+ SeparationConstraint *separation479628624 = new SeparationConstraint(vpsc::XDIM, 28, 30, -54, true);
+ ccs.push_back(separation479628624);
+
+ SeparationConstraint *separation479628816 = new SeparationConstraint(vpsc::YDIM, 28, 30, 9, true);
+ ccs.push_back(separation479628816);
+
+ SeparationConstraint *separation479628752 = new SeparationConstraint(vpsc::XDIM, 31, 32, 66.5, true);
+ ccs.push_back(separation479628752);
+
+ SeparationConstraint *separation479622736 = new SeparationConstraint(vpsc::YDIM, 31, 32, -5.7, true);
+ ccs.push_back(separation479622736);
+
+ SeparationConstraint *separation479622800 = new SeparationConstraint(vpsc::XDIM, 31, 33, 66.5, true);
+ ccs.push_back(separation479622800);
+
+ SeparationConstraint *separation479622864 = new SeparationConstraint(vpsc::YDIM, 31, 33, 4.1, true);
+ ccs.push_back(separation479622864);
+
+ SeparationConstraint *separation479622928 = new SeparationConstraint(vpsc::XDIM, 31, 34, 66.5, true);
+ ccs.push_back(separation479622928);
+
+ SeparationConstraint *separation479622992 = new SeparationConstraint(vpsc::YDIM, 31, 34, 13.9, true);
+ ccs.push_back(separation479622992);
+
+ SeparationConstraint *separation479623056 = new SeparationConstraint(vpsc::XDIM, 31, 35, 66.5, true);
+ ccs.push_back(separation479623056);
+
+ SeparationConstraint *separation479623120 = new SeparationConstraint(vpsc::YDIM, 31, 35, 23.7, true);
+ ccs.push_back(separation479623120);
+
+ SeparationConstraint *separation479623184 = new SeparationConstraint(vpsc::XDIM, 31, 36, -66.5, true);
+ ccs.push_back(separation479623184);
+
+ SeparationConstraint *separation479623248 = new SeparationConstraint(vpsc::YDIM, 31, 36, 9, true);
+ ccs.push_back(separation479623248);
+
+ SeparationConstraint *separation479623312 = new SeparationConstraint(vpsc::XDIM, 37, 38, 39, true);
+ ccs.push_back(separation479623312);
+
+ SeparationConstraint *separation479623440 = new SeparationConstraint(vpsc::YDIM, 37, 38, 9, true);
+ ccs.push_back(separation479623440);
+
+ SeparationConstraint *separation479623504 = new SeparationConstraint(vpsc::XDIM, 37, 39, -39, true);
+ ccs.push_back(separation479623504);
+
+ SeparationConstraint *separation479623568 = new SeparationConstraint(vpsc::YDIM, 37, 39, 9, true);
+ ccs.push_back(separation479623568);
+
+ SeparationConstraint *separation479623632 = new SeparationConstraint(vpsc::XDIM, 40, 41, 39, true);
+ ccs.push_back(separation479623632);
+
+ SeparationConstraint *separation479623696 = new SeparationConstraint(vpsc::YDIM, 40, 41, 9, true);
+ ccs.push_back(separation479623696);
+
+ SeparationConstraint *separation479623760 = new SeparationConstraint(vpsc::XDIM, 40, 42, -39, true);
+ ccs.push_back(separation479623760);
+
+ SeparationConstraint *separation479623888 = new SeparationConstraint(vpsc::YDIM, 40, 42, 9, true);
+ ccs.push_back(separation479623888);
+
+ SeparationConstraint *separation479623952 = new SeparationConstraint(vpsc::XDIM, 43, 44, 103, true);
+ ccs.push_back(separation479623952);
+
+ SeparationConstraint *separation479624016 = new SeparationConstraint(vpsc::YDIM, 43, 44, 9, true);
+ ccs.push_back(separation479624016);
+
+ SeparationConstraint *separation479624080 = new SeparationConstraint(vpsc::XDIM, 43, 45, -103, true);
+ ccs.push_back(separation479624080);
+
+ SeparationConstraint *separation479624144 = new SeparationConstraint(vpsc::YDIM, 43, 45, 27.9, true);
+ ccs.push_back(separation479624144);
+
+ SeparationConstraint *separation479624208 = new SeparationConstraint(vpsc::XDIM, 43, 46, -103, true);
+ ccs.push_back(separation479624208);
+
+ SeparationConstraint *separation479624272 = new SeparationConstraint(vpsc::YDIM, 43, 46, 15.3, true);
+ ccs.push_back(separation479624272);
+
+ SeparationConstraint *separation479624336 = new SeparationConstraint(vpsc::XDIM, 43, 47, -103, true);
+ ccs.push_back(separation479624336);
+
+ SeparationConstraint *separation479624400 = new SeparationConstraint(vpsc::YDIM, 43, 47, 2.7, true);
+ ccs.push_back(separation479624400);
+
+ SeparationConstraint *separation479624528 = new SeparationConstraint(vpsc::XDIM, 43, 48, -103, true);
+ ccs.push_back(separation479624528);
+
+ SeparationConstraint *separation479624592 = new SeparationConstraint(vpsc::YDIM, 43, 48, -9.9, true);
+ ccs.push_back(separation479624592);
+
+ SeparationConstraint *separation479624656 = new SeparationConstraint(vpsc::XDIM, 49, 50, 39, true);
+ ccs.push_back(separation479624656);
+
+ SeparationConstraint *separation479624720 = new SeparationConstraint(vpsc::YDIM, 49, 50, 9, true);
+ ccs.push_back(separation479624720);
+
+ SeparationConstraint *separation479624784 = new SeparationConstraint(vpsc::XDIM, 49, 51, -39, true);
+ ccs.push_back(separation479624784);
+
+ SeparationConstraint *separation479624848 = new SeparationConstraint(vpsc::YDIM, 49, 51, 9, true);
+ ccs.push_back(separation479624848);
+
+ SeparationConstraint *separation479624912 = new SeparationConstraint(vpsc::XDIM, 52, 53, 40, true);
+ ccs.push_back(separation479624912);
+
+ SeparationConstraint *separation479624976 = new SeparationConstraint(vpsc::YDIM, 52, 53, 9, true);
+ ccs.push_back(separation479624976);
+
+ SeparationConstraint *separation479625040 = new SeparationConstraint(vpsc::XDIM, 52, 54, -40, true);
+ ccs.push_back(separation479625040);
+
+ SeparationConstraint *separation479625104 = new SeparationConstraint(vpsc::YDIM, 52, 54, 15.5, true);
+ ccs.push_back(separation479625104);
+
+ SeparationConstraint *separation479625168 = new SeparationConstraint(vpsc::XDIM, 52, 55, -40, true);
+ ccs.push_back(separation479625168);
+
+ SeparationConstraint *separation479625232 = new SeparationConstraint(vpsc::YDIM, 52, 55, 2.5, true);
+ ccs.push_back(separation479625232);
+
+ SeparationConstraint *separation479625296 = new SeparationConstraint(vpsc::XDIM, 56, 57, 36.5, true);
+ ccs.push_back(separation479625296);
+
+ SeparationConstraint *separation479625360 = new SeparationConstraint(vpsc::YDIM, 56, 57, 9, true);
+ ccs.push_back(separation479625360);
+
+ SeparationConstraint *separation479625424 = new SeparationConstraint(vpsc::XDIM, 56, 58, -36.5, true);
+ ccs.push_back(separation479625424);
+
+ SeparationConstraint *separation479625552 = new SeparationConstraint(vpsc::YDIM, 56, 58, 9, true);
+ ccs.push_back(separation479625552);
+
+ SeparationConstraint *separation479625616 = new SeparationConstraint(vpsc::XDIM, 59, 60, -43, true);
+ ccs.push_back(separation479625616);
+
+ SeparationConstraint *separation479625680 = new SeparationConstraint(vpsc::YDIM, 59, 60, 9, true);
+ ccs.push_back(separation479625680);
+
+ SeparationConstraint *separation479625744 = new SeparationConstraint(vpsc::XDIM, 61, 62, 62, true);
+ ccs.push_back(separation479625744);
+
+ SeparationConstraint *separation479625488 = new SeparationConstraint(vpsc::YDIM, 61, 62, 9, true);
+ ccs.push_back(separation479625488);
+
+ SeparationConstraint *separation479624464 = new SeparationConstraint(vpsc::XDIM, 61, 63, -62, true);
+ ccs.push_back(separation479624464);
+
+ SeparationConstraint *separation479623824 = new SeparationConstraint(vpsc::YDIM, 61, 63, 9, true);
+ ccs.push_back(separation479623824);
+
+ SeparationConstraint *separation479623376 = new SeparationConstraint(vpsc::XDIM, 64, 65, 41, true);
+ ccs.push_back(separation479623376);
+
+ SeparationConstraint *separation479628944 = new SeparationConstraint(vpsc::YDIM, 64, 65, 9, true);
+ ccs.push_back(separation479628944);
+
+ SeparationConstraint *separation479628880 = new SeparationConstraint(vpsc::XDIM, 64, 66, -4.5, true);
+ ccs.push_back(separation479628880);
+
+ SeparationConstraint *separation479629008 = new SeparationConstraint(vpsc::YDIM, 64, 66, 50.5, true);
+ ccs.push_back(separation479629008);
+
+ SeparationConstraint *separation479629072 = new SeparationConstraint(vpsc::XDIM, 64, 67, -41, true);
+ ccs.push_back(separation479629072);
+
+ SeparationConstraint *separation479629136 = new SeparationConstraint(vpsc::YDIM, 64, 67, 9, true);
+ ccs.push_back(separation479629136);
+
+ SeparationConstraint *separation479629200 = new SeparationConstraint(vpsc::XDIM, 68, 69, 30.5, true);
+ ccs.push_back(separation479629200);
+
+ SeparationConstraint *separation479629264 = new SeparationConstraint(vpsc::YDIM, 68, 69, 9, true);
+ ccs.push_back(separation479629264);
+
+ SeparationConstraint *separation479629328 = new SeparationConstraint(vpsc::XDIM, 68, 70, -30.5, true);
+ ccs.push_back(separation479629328);
+
+ SeparationConstraint *separation479629392 = new SeparationConstraint(vpsc::YDIM, 68, 70, 17.1667, true);
+ ccs.push_back(separation479629392);
+
+ SeparationConstraint *separation479629456 = new SeparationConstraint(vpsc::XDIM, 68, 71, -30.5, true);
+ ccs.push_back(separation479629456);
+
+ SeparationConstraint *separation479629520 = new SeparationConstraint(vpsc::YDIM, 68, 71, 0.833333, true);
+ ccs.push_back(separation479629520);
+
+ SeparationConstraint *separation479629584 = new SeparationConstraint(vpsc::XDIM, 72, 73, 49.5, true);
+ ccs.push_back(separation479629584);
+
+ SeparationConstraint *separation479629648 = new SeparationConstraint(vpsc::YDIM, 72, 73, 9, true);
+ ccs.push_back(separation479629648);
+
+ SeparationConstraint *separation479629712 = new SeparationConstraint(vpsc::XDIM, 72, 74, -49.5, true);
+ ccs.push_back(separation479629712);
+
+ SeparationConstraint *separation479629776 = new SeparationConstraint(vpsc::YDIM, 72, 74, 17.1667, true);
+ ccs.push_back(separation479629776);
+
+ SeparationConstraint *separation479629840 = new SeparationConstraint(vpsc::XDIM, 72, 75, -49.5, true);
+ ccs.push_back(separation479629840);
+
+ SeparationConstraint *separation479629904 = new SeparationConstraint(vpsc::YDIM, 72, 75, 0.833333, true);
+ ccs.push_back(separation479629904);
+
+ SeparationConstraint *separation479629968 = new SeparationConstraint(vpsc::XDIM, 76, 77, 37, true);
+ ccs.push_back(separation479629968);
+
+ SeparationConstraint *separation479630032 = new SeparationConstraint(vpsc::YDIM, 76, 77, 9, true);
+ ccs.push_back(separation479630032);
+
+ SeparationConstraint *separation479630096 = new SeparationConstraint(vpsc::XDIM, 76, 78, -37, true);
+ ccs.push_back(separation479630096);
+
+ SeparationConstraint *separation479630160 = new SeparationConstraint(vpsc::YDIM, 76, 78, 9, true);
+ ccs.push_back(separation479630160);
+
+ SeparationConstraint *separation479630224 = new SeparationConstraint(vpsc::XDIM, 79, 80, 37, true);
+ ccs.push_back(separation479630224);
+
+ SeparationConstraint *separation479630288 = new SeparationConstraint(vpsc::YDIM, 79, 80, 9, true);
+ ccs.push_back(separation479630288);
+
+ SeparationConstraint *separation479630352 = new SeparationConstraint(vpsc::XDIM, 79, 81, -0.333334, true);
+ ccs.push_back(separation479630352);
+
+ SeparationConstraint *separation479630416 = new SeparationConstraint(vpsc::YDIM, 79, 81, 53, true);
+ ccs.push_back(separation479630416);
+
+ SeparationConstraint *separation477486176 = new SeparationConstraint(vpsc::XDIM, 79, 82, -17.6667, true);
+ ccs.push_back(separation477486176);
+
+ SeparationConstraint *separation477486240 = new SeparationConstraint(vpsc::YDIM, 79, 82, 53, true);
+ ccs.push_back(separation477486240);
+
+ SeparationConstraint *separation477486304 = new SeparationConstraint(vpsc::XDIM, 79, 83, -37, true);
+ ccs.push_back(separation477486304);
+
+ SeparationConstraint *separation477486368 = new SeparationConstraint(vpsc::YDIM, 79, 83, 9, true);
+ ccs.push_back(separation477486368);
+
+ SeparationConstraint *separation477486432 = new SeparationConstraint(vpsc::XDIM, 84, 85, 33.5, true);
+ ccs.push_back(separation477486432);
+
+ SeparationConstraint *separation477486496 = new SeparationConstraint(vpsc::YDIM, 84, 85, 9, true);
+ ccs.push_back(separation477486496);
+
+ SeparationConstraint *separation477486560 = new SeparationConstraint(vpsc::XDIM, 84, 86, 3.16667, true);
+ ccs.push_back(separation477486560);
+
+ SeparationConstraint *separation477486624 = new SeparationConstraint(vpsc::YDIM, 84, 86, 53, true);
+ ccs.push_back(separation477486624);
+
+ SeparationConstraint *separation477486688 = new SeparationConstraint(vpsc::XDIM, 84, 87, -14.1667, true);
+ ccs.push_back(separation477486688);
+
+ SeparationConstraint *separation477486752 = new SeparationConstraint(vpsc::YDIM, 84, 87, 53, true);
+ ccs.push_back(separation477486752);
+
+ SeparationConstraint *separation477486816 = new SeparationConstraint(vpsc::XDIM, 84, 88, -33.5, true);
+ ccs.push_back(separation477486816);
+
+ SeparationConstraint *separation477486880 = new SeparationConstraint(vpsc::YDIM, 84, 88, 9, true);
+ ccs.push_back(separation477486880);
+
+ SeparationConstraint *separation477486944 = new SeparationConstraint(vpsc::XDIM, 89, 90, 48, true);
+ ccs.push_back(separation477486944);
+
+ SeparationConstraint *separation477487008 = new SeparationConstraint(vpsc::YDIM, 89, 90, 9, true);
+ ccs.push_back(separation477487008);
+
+ SeparationConstraint *separation477487072 = new SeparationConstraint(vpsc::XDIM, 89, 91, -48, true);
+ ccs.push_back(separation477487072);
+
+ SeparationConstraint *separation477487136 = new SeparationConstraint(vpsc::YDIM, 89, 91, 9, true);
+ ccs.push_back(separation477487136);
+
+ SeparationConstraint *separation477487200 = new SeparationConstraint(vpsc::XDIM, 7, 0, 137, false);
+ ccs.push_back(separation477487200);
+
+ SeparationConstraint *separation477487264 = new SeparationConstraint(vpsc::XDIM, 0, 5, 118.5, false);
+ ccs.push_back(separation477487264);
+
+ SeparationConstraint *separation477487328 = new SeparationConstraint(vpsc::XDIM, 79, 5, 118, false);
+ ccs.push_back(separation477487328);
+
+ SeparationConstraint *separation477487392 = new SeparationConstraint(vpsc::XDIM, 9, 15, 146.5, false);
+ ccs.push_back(separation477487392);
+
+ SeparationConstraint *separation477487456 = new SeparationConstraint(vpsc::XDIM, 28, 15, 139, false);
+ ccs.push_back(separation477487456);
+
+ SeparationConstraint *separation477487520 = new SeparationConstraint(vpsc::XDIM, 0, 22, 142.5, false);
+ ccs.push_back(separation477487520);
+
+ SeparationConstraint *separation477487584 = new SeparationConstraint(vpsc::XDIM, 0, 22, 142.5, false);
+ ccs.push_back(separation477487584);
+
+ SeparationConstraint *separation477487648 = new SeparationConstraint(vpsc::XDIM, 0, 22, 142.5, false);
+ ccs.push_back(separation477487648);
+
+ SeparationConstraint *separation477487712 = new SeparationConstraint(vpsc::XDIM, 19, 22, 137.5, false);
+ ccs.push_back(separation477487712);
+
+ SeparationConstraint *separation477487776 = new SeparationConstraint(vpsc::XDIM, 22, 28, 150, false);
+ ccs.push_back(separation477487776);
+
+ SeparationConstraint *separation477487840 = new SeparationConstraint(vpsc::XDIM, 15, 31, 151.5, false);
+ ccs.push_back(separation477487840);
+
+ SeparationConstraint *separation477487904 = new SeparationConstraint(vpsc::XDIM, 31, 37, 143.5, false);
+ ccs.push_back(separation477487904);
+
+ SeparationConstraint *separation477487968 = new SeparationConstraint(vpsc::XDIM, 31, 40, 143.5, false);
+ ccs.push_back(separation477487968);
+
+ SeparationConstraint *separation477488032 = new SeparationConstraint(vpsc::XDIM, 31, 43, 207.5, false);
+ ccs.push_back(separation477488032);
+
+ SeparationConstraint *separation477488096 = new SeparationConstraint(vpsc::XDIM, 37, 43, 235, false);
+ ccs.push_back(separation477488096);
+
+ SeparationConstraint *separation477488160 = new SeparationConstraint(vpsc::XDIM, 40, 43, 235, false);
+ ccs.push_back(separation477488160);
+
+ SeparationConstraint *separation477488224 = new SeparationConstraint(vpsc::XDIM, 49, 43, 235, false);
+ ccs.push_back(separation477488224);
+
+ SeparationConstraint *separation477488288 = new SeparationConstraint(vpsc::XDIM, 31, 49, 143.5, false);
+ ccs.push_back(separation477488288);
+
+ SeparationConstraint *separation477488352 = new SeparationConstraint(vpsc::XDIM, 31, 52, 217.5, false);
+ ccs.push_back(separation477488352);
+
+ SeparationConstraint *separation477488416 = new SeparationConstraint(vpsc::XDIM, 43, 52, 181, false);
+ ccs.push_back(separation477488416);
+
+ SeparationConstraint *separation477488480 = new SeparationConstraint(vpsc::XDIM, 52, 56, 114.5, false);
+ ccs.push_back(separation477488480);
+
+ SeparationConstraint *separation477488544 = new SeparationConstraint(vpsc::XDIM, 61, 59, 143, false);
+ ccs.push_back(separation477488544);
+
+ SeparationConstraint *separation477488608 = new SeparationConstraint(vpsc::XDIM, 56, 61, 136.5, false);
+ ccs.push_back(separation477488608);
+
+ SeparationConstraint *separation477488672 = new SeparationConstraint(vpsc::XDIM, 15, 64, 126, false);
+ ccs.push_back(separation477488672);
+
+ SeparationConstraint *separation477488736 = new SeparationConstraint(vpsc::XDIM, 56, 64, 136.5, false);
+ ccs.push_back(separation477488736);
+
+ SeparationConstraint *separation477488800 = new SeparationConstraint(vpsc::XDIM, 89, 68, 116.5, false);
+ ccs.push_back(separation477488800);
+
+ SeparationConstraint *separation477488864 = new SeparationConstraint(vpsc::XDIM, 68, 72, 131, false);
+ ccs.push_back(separation477488864);
+
+ SeparationConstraint *separation477488928 = new SeparationConstraint(vpsc::XDIM, 76, 72, 124.5, false);
+ ccs.push_back(separation477488928);
+
+ SeparationConstraint *separation477488992 = new SeparationConstraint(vpsc::XDIM, 84, 79, 108.5, false);
+ ccs.push_back(separation477488992);
+
+ SeparationConstraint *separation477489056 = new SeparationConstraint(vpsc::XDIM, 72, 84, 121, false);
+ ccs.push_back(separation477489056);
+
+ SeparationConstraint *separation477489120 = new SeparationConstraint(vpsc::XDIM, 64, 89, 127, false);
+ ccs.push_back(separation477489120);
+
+ cola::Box margin = cola::Box(10, 30, 30, 60); //30
+ cola::Box padding = cola::Box(); // cola::Box(10, 30, 30, 60); //10
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);
+ RootCluster *cluster476902600 = new RootCluster();
+ cluster476902600->addChildNode(0);
+ cluster476902600->addChildNode(1);
+ cluster476902600->addChildNode(2);
+ cluster476902600->addChildNode(3);
+ cluster476902600->addChildNode(4);
+ cluster476902600->addChildNode(5);
+ cluster476902600->addChildNode(6);
+ cluster476902600->addChildNode(7);
+ cluster476902600->addChildNode(8);
+ cluster476902600->addChildNode(9);
+ cluster476902600->addChildNode(10);
+ cluster476902600->addChildNode(11);
+ cluster476902600->addChildNode(12);
+ cluster476902600->addChildNode(13);
+ cluster476902600->addChildNode(14);
+ cluster476902600->addChildNode(15);
+ cluster476902600->addChildNode(16);
+ cluster476902600->addChildNode(17);
+ cluster476902600->addChildNode(18);
+ cluster476902600->addChildNode(19);
+ cluster476902600->addChildNode(20);
+ cluster476902600->addChildNode(21);
+ cluster476902600->addChildNode(22);
+ cluster476902600->addChildNode(23);
+ cluster476902600->addChildNode(24);
+ cluster476902600->addChildNode(25);
+ cluster476902600->addChildNode(26);
+ cluster476902600->addChildNode(27);
+ cluster476902600->addChildNode(28);
+ cluster476902600->addChildNode(29);
+ cluster476902600->addChildNode(30);
+ RectangularCluster *cluster417213744 = new RectangularCluster();
+ cluster417213744->setMargin(margin);
+ cluster417213744->setPadding(padding);
+ cluster417213744->addChildNode(59);
+ cluster417213744->addChildNode(60);
+ cluster417213744->addChildNode(61);
+ cluster417213744->addChildNode(62);
+ cluster417213744->addChildNode(63);
+ cluster417213744->addChildNode(64);
+ cluster417213744->addChildNode(65);
+ cluster417213744->addChildNode(66);
+ cluster417213744->addChildNode(67);
+ cluster417213744->addChildNode(89);
+ cluster417213744->addChildNode(90);
+ cluster417213744->addChildNode(91);
+ RectangularCluster *cluster417215984 = new RectangularCluster();
+ cluster417215984->setMargin(margin);
+ cluster417215984->setPadding(padding);
+ cluster417215984->addChildNode(31);
+ cluster417215984->addChildNode(32);
+ cluster417215984->addChildNode(33);
+ cluster417215984->addChildNode(34);
+ cluster417215984->addChildNode(35);
+ cluster417215984->addChildNode(36);
+ cluster417215984->addChildNode(37);
+ cluster417215984->addChildNode(38);
+ cluster417215984->addChildNode(39);
+ cluster417215984->addChildNode(40);
+ cluster417215984->addChildNode(41);
+ cluster417215984->addChildNode(42);
+ cluster417215984->addChildNode(43);
+ cluster417215984->addChildNode(44);
+ cluster417215984->addChildNode(45);
+ cluster417215984->addChildNode(46);
+ cluster417215984->addChildNode(47);
+ cluster417215984->addChildNode(48);
+ cluster417215984->addChildNode(49);
+ cluster417215984->addChildNode(50);
+ cluster417215984->addChildNode(51);
+ cluster417215984->addChildNode(52);
+ cluster417215984->addChildNode(53);
+ cluster417215984->addChildNode(54);
+ cluster417215984->addChildNode(55);
+ cluster417215984->addChildNode(56);
+ cluster417215984->addChildNode(57);
+ cluster417215984->addChildNode(58);
+ cluster417213744->addChildCluster(cluster417215984);
+ RectangularCluster *cluster417215760 = new RectangularCluster();
+ cluster417215760->setMargin(margin);
+ cluster417215760->setPadding(padding);
+ cluster417215760->addChildNode(68);
+ cluster417215760->addChildNode(69);
+ cluster417215760->addChildNode(70);
+ cluster417215760->addChildNode(71);
+ cluster417215760->addChildNode(72);
+ cluster417215760->addChildNode(73);
+ cluster417215760->addChildNode(74);
+ cluster417215760->addChildNode(75);
+ cluster417215760->addChildNode(76);
+ cluster417215760->addChildNode(77);
+ cluster417215760->addChildNode(78);
+ cluster417215760->addChildNode(79);
+ cluster417215760->addChildNode(80);
+ cluster417215760->addChildNode(81);
+ cluster417215760->addChildNode(82);
+ cluster417215760->addChildNode(83);
+ cluster417215760->addChildNode(84);
+ cluster417215760->addChildNode(85);
+ cluster417215760->addChildNode(86);
+ cluster417215760->addChildNode(87);
+ cluster417215760->addChildNode(88);
+ cluster417213744->addChildCluster(cluster417215760);
+ cluster476902600->addChildCluster(cluster417213744);
+ alg.setClusterHierarchy(cluster476902600);
+ alg.setConstraints(ccs);
+
+ UnsatisfiableConstraintInfos unsatisfiableX, unsatisfiableY;
+ alg.setUnsatisfiableConstraintInfo(&unsatisfiableX, &unsatisfiableY);
+
+ // rect-43 and associated port rects.
+ cola::NodeIndexes nonOverlapExemptGroup;
+ nonOverlapExemptGroup.push_back(44);
+ nonOverlapExemptGroup.push_back(45);
+ nonOverlapExemptGroup.push_back(46);
+ nonOverlapExemptGroup.push_back(47);
+ nonOverlapExemptGroup.push_back(48);
+ nonOverlapExemptGroup.push_back(43);
+
+ std::vector<cola::NodeIndexes> nonOverlapExemptGroupList;
+ nonOverlapExemptGroupList.push_back(nonOverlapExemptGroup);
+ alg.setAvoidNodeOverlaps(true, nonOverlapExemptGroupList);
+
+ //alg.makeFeasible();
+ alg.run();
+ alg.outputInstanceToSVG("rectangularClusters01");
+
+ for (size_t i = 0; i < unsatisfiableX.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableX[i]->toString().c_str());
+ }
+ for (size_t i = 0; i < unsatisfiableY.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableY[i]->toString().c_str());
+ }
+ alg.freeAssociatedObjects();
+ return (unsatisfiableX.empty() && unsatisfiableY.empty()) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/rectclustershapecontainment.cpp b/src/3rdparty/adaptagrams/libcola/tests/rectclustershapecontainment.cpp new file mode 100644 index 0000000..3c3d704 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/rectclustershapecontainment.cpp @@ -0,0 +1,2173 @@ +#include <vector> +#include "libcola/cola.h" +using namespace cola; +int main(void) { + CompoundConstraints ccs; + std::vector<Edge> es; + double defaultEdgeLength=40; + std::vector<vpsc::Rectangle*> rs; + vpsc::Rectangle *rect = nullptr; + + rect = new vpsc::Rectangle(478, 488, 399, 409); + rs.push_back(rect); + + rect = new vpsc::Rectangle(284, 294, 938, 948); + rs.push_back(rect); + + rect = new vpsc::Rectangle(141, 151, 906, 916); + rs.push_back(rect); + + rect = new vpsc::Rectangle(284, 294, 959, 969); + rs.push_back(rect); + + rect = new vpsc::Rectangle(131, 161, 938, 968); + rs.push_back(rect); + + rect = new vpsc::Rectangle(550, 762, 155.5, 522.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(430, 540, -6, 158); + rs.push_back(rect); + + rect = new vpsc::Rectangle(373, 383, 907, 917); + rs.push_back(rect); + + rect = new vpsc::Rectangle(482, 492, 938, 948); + rs.push_back(rect); + + rect = new vpsc::Rectangle(434, 444, 938, 948); + rs.push_back(rect); + + rect = new vpsc::Rectangle(426, 436, 869, 879); + rs.push_back(rect); + + rect = new vpsc::Rectangle(426, 436, 848, 858); + rs.push_back(rect); + + rect = new vpsc::Rectangle(314, 324, 860, 870); + rs.push_back(rect); + + rect = new vpsc::Rectangle(205, 215, 860, 870); + rs.push_back(rect); + + rect = new vpsc::Rectangle(553, 563, 859, 869); + rs.push_back(rect); + + rect = new vpsc::Rectangle(345, 423, 746, 780); + rs.push_back(rect); + + rect = new vpsc::Rectangle(478, 488, 765, 775); + rs.push_back(rect); + + rect = new vpsc::Rectangle(-34.5, 162.5, 723, 877); + rs.push_back(rect); + + rect = new vpsc::Rectangle(478, 488, 696, 706); + rs.push_back(rect); + + rect = new vpsc::Rectangle(478, 488, 624, 634); + rs.push_back(rect); + + rect = new vpsc::Rectangle(453, 463, 479, 489); + rs.push_back(rect); + + rect = new vpsc::Rectangle(154.5, 457.5, 574, 624); + rs.push_back(rect); + + rect = new vpsc::Rectangle(398, 408, 445, 455); + rs.push_back(rect); + + rect = new vpsc::Rectangle(453, 463, 331, 341); + rs.push_back(rect); + + rect = new vpsc::Rectangle(403, 413, 331, 341); + rs.push_back(rect); + + rect = new vpsc::Rectangle(547, 557, 191, 201); + rs.push_back(rect); + + rect = new vpsc::Rectangle(478, 488, 260, 270); + rs.push_back(rect); + + rect = new vpsc::Rectangle(478, 488, 168, 178); + rs.push_back(rect); + + rect = new vpsc::Rectangle(380, 390, 297, 307); + rs.push_back(rect); + + rect = new vpsc::Rectangle(228, 238, 286, 296); + rs.push_back(rect); + + rect = new vpsc::Rectangle(228, 238, 307, 317); + rs.push_back(rect); + + rect = new vpsc::Rectangle(352, 362, 259, 269); + rs.push_back(rect); + + rect = new vpsc::Rectangle(302, 312, 259, 269); + rs.push_back(rect); + + rect = new vpsc::Rectangle(176, 186, 259, 269); + rs.push_back(rect); + + rect = new vpsc::Rectangle(228, 238, 234, 244); + rs.push_back(rect); + + rect = new vpsc::Rectangle(228, 238, 213, 223); + rs.push_back(rect); + + rect = new vpsc::Rectangle(311, 321, 181, 191); + rs.push_back(rect); + + rect = new vpsc::Rectangle(338, 348, 149, 159); + rs.push_back(rect); + + rect = new vpsc::Rectangle(338, 348, 128, 138); + rs.push_back(rect); + + rect = new vpsc::Rectangle(40.5, 291.5, 45.5, 70.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(257, 267, 903, 913); + rs.push_back(rect); + + rect = new vpsc::Rectangle(478, 488, 551, 561); + rs.push_back(rect); + + rect = new vpsc::Rectangle(276, 286, 213, 223); + rs.push_back(rect); + + rect = new vpsc::Rectangle(276, 286, 286, 296); + rs.push_back(rect); + + rect = new vpsc::Rectangle(176, 186, 355, 365); + rs.push_back(rect); + + rect = new vpsc::Rectangle(176, 186, 381, 391); + rs.push_back(rect); + + rect = new vpsc::Rectangle(286, 296, 354, 364); + rs.push_back(rect); + + rect = new vpsc::Rectangle(286, 296, 380, 390); + rs.push_back(rect); + + rect = new vpsc::Rectangle(586, 616, 180, 210); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 128, 158); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 649, 679); + rs.push_back(rect); + + rect = new vpsc::Rectangle(166, 196, 213, 243); + rs.push_back(rect); + + rect = new vpsc::Rectangle(166, 196, 286, 316); + rs.push_back(rect); + + rect = new vpsc::Rectangle(317, 347, 433, 463); + rs.push_back(rect); + + rect = new vpsc::Rectangle(317, 347, 286, 316); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 215, 245); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 288, 318); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 721, 751); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 577, 607); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 505, 535); + rs.push_back(rect); + + rect = new vpsc::Rectangle(612, 642, 848, 878); + rs.push_back(rect); + + rect = new vpsc::Rectangle(299, 329, 891, 921); + rs.push_back(rect); + + rect = new vpsc::Rectangle(535, 565, 938, 968); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 848, 878); + rs.push_back(rect); + + rect = new vpsc::Rectangle(363, 393, 848, 878); + rs.push_back(rect); + + rect = new vpsc::Rectangle(131, 161, 848, 878); + rs.push_back(rect); + + rect = new vpsc::Rectangle(363, 393, 938, 968); + rs.push_back(rect); + + rect = new vpsc::Rectangle(250, 280, 848, 878); + rs.push_back(rect); + + rect = new vpsc::Rectangle(197, 227, 891, 921); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 358, 388); + rs.push_back(rect); + + rect = new vpsc::Rectangle(117, 147, 344, 374); + rs.push_back(rect); + + rect = new vpsc::Rectangle(224, 254, 344, 374); + rs.push_back(rect); + + rect = new vpsc::Rectangle(224, 254, 370, 400); + rs.push_back(rect); + + rect = new vpsc::Rectangle(117, 147, 370, 400); + rs.push_back(rect); + + rect = new vpsc::Rectangle(363, 393, 805, 835); + rs.push_back(rect); + + rect = new vpsc::Rectangle(181, 227, 711, 741); + rs.push_back(rect); + + rect = new vpsc::Rectangle(131, 161, 721, 751); + rs.push_back(rect); + + rect = new vpsc::Rectangle(434, 444, 959, 969); + rs.push_back(rect); + + rect = new vpsc::Rectangle(199, 209, 742, 752); + rs.push_back(rect); + + rect = new vpsc::Rectangle(482, 492, 959, 969); + rs.push_back(rect); + + rect = new vpsc::Rectangle(565.5, 692.5, 842.5, 997.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(503, 513, 479, 489); + rs.push_back(rect); + + rect = new vpsc::Rectangle(577, 587, 520, 530); + rs.push_back(rect); + + rect = new vpsc::Rectangle(550, 560, 539, 549); + rs.push_back(rect); + + rect = new vpsc::Rectangle(284, 294, 790, 800); + rs.push_back(rect); + + rect = new vpsc::Rectangle(527, 537, 520, 530); + rs.push_back(rect); + + rect = new vpsc::Rectangle(383, 413, 541, 571); + rs.push_back(rect); + + rect = new vpsc::Rectangle(432, 442, 581, 591); + rs.push_back(rect); + + rect = new vpsc::Rectangle(433, 443, 517, 527); + rs.push_back(rect); + + rect = new vpsc::Rectangle(468, 498, 433, 463); + rs.push_back(rect); + + rect = new vpsc::Rectangle(91, 101, 906, 916); + rs.push_back(rect); + + rect = new vpsc::Rectangle(503, 513, 331, 341); + rs.push_back(rect); + + rect = new vpsc::Rectangle(276, 286, 234, 244); + rs.push_back(rect); + + rect = new vpsc::Rectangle(276, 286, 307, 317); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 568, 389, 419); + rs.push_back(rect); + + rect = new vpsc::Rectangle(266, 312, 878, 908); + rs.push_back(rect); + + rect = new vpsc::Rectangle(185, 231, 896, 926); + rs.push_back(rect); + + rect = new vpsc::Rectangle(266, 312, 899, 929); + rs.push_back(rect); + + rect = new vpsc::Rectangle(417, 463, 897, 927); + rs.push_back(rect); + + rect = new vpsc::Rectangle(464, 510, 878, 908); + rs.push_back(rect); + + rect = new vpsc::Rectangle(416, 462, 878, 908); + rs.push_back(rect); + + rect = new vpsc::Rectangle(470, 516, 859, 889); + rs.push_back(rect); + + rect = new vpsc::Rectangle(470, 516, 838, 868); + rs.push_back(rect); + + rect = new vpsc::Rectangle(358, 404, 850, 880); + rs.push_back(rect); + + rect = new vpsc::Rectangle(187, 233, 800, 830); + rs.push_back(rect); + + rect = new vpsc::Rectangle(535, 581, 799, 829); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 568, 755, 785); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 568, 686, 716); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 568, 614, 644); + rs.push_back(rect); + + rect = new vpsc::Rectangle(497, 543, 469, 499); + rs.push_back(rect); + + rect = new vpsc::Rectangle(380, 426, 385, 415); + rs.push_back(rect); + + rect = new vpsc::Rectangle(497, 543, 321, 351); + rs.push_back(rect); + + rect = new vpsc::Rectangle(385, 431, 271, 301); + rs.push_back(rect); + + rect = new vpsc::Rectangle(529, 575, 131, 161); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 568, 250, 280); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 568, 158, 188); + rs.push_back(rect); + + rect = new vpsc::Rectangle(362, 408, 237, 267); + rs.push_back(rect); + + rect = new vpsc::Rectangle(210, 256, 226, 256); + rs.push_back(rect); + + rect = new vpsc::Rectangle(210, 256, 247, 277); + rs.push_back(rect); + + rect = new vpsc::Rectangle(396, 442, 249, 279); + rs.push_back(rect); + + rect = new vpsc::Rectangle(346, 392, 249, 279); + rs.push_back(rect); + + rect = new vpsc::Rectangle(220, 266, 249, 279); + rs.push_back(rect); + + rect = new vpsc::Rectangle(210, 256, 174, 204); + rs.push_back(rect); + + rect = new vpsc::Rectangle(210, 256, 153, 183); + rs.push_back(rect); + + rect = new vpsc::Rectangle(293, 339, 121, 151); + rs.push_back(rect); + + rect = new vpsc::Rectangle(320, 366, 89, 119); + rs.push_back(rect); + + rect = new vpsc::Rectangle(320, 366, 68, 98); + rs.push_back(rect); + + rect = new vpsc::Rectangle(239, 285, 843, 873); + rs.push_back(rect); + + rect = new vpsc::Rectangle(522, 568, 541, 571); + rs.push_back(rect); + + rect = new vpsc::Rectangle(258, 304, 153, 183); + rs.push_back(rect); + + rect = new vpsc::Rectangle(258, 304, 226, 256); + rs.push_back(rect); + + rect = new vpsc::Rectangle(158, 204, 295, 325); + rs.push_back(rect); + + rect = new vpsc::Rectangle(158, 204, 321, 351); + rs.push_back(rect); + + rect = new vpsc::Rectangle(268, 314, 294, 324); + rs.push_back(rect); + + rect = new vpsc::Rectangle(268, 314, 320, 350); + rs.push_back(rect); + + rect = new vpsc::Rectangle(416, 462, 899, 929); + rs.push_back(rect); + + rect = new vpsc::Rectangle(181, 227, 682, 712); + rs.push_back(rect); + + rect = new vpsc::Rectangle(464, 510, 899, 929); + rs.push_back(rect); + + rect = new vpsc::Rectangle(547, 593, 469, 499); + rs.push_back(rect); + + rect = new vpsc::Rectangle(559, 605, 460, 490); + rs.push_back(rect); + + rect = new vpsc::Rectangle(532, 578, 479, 509); + rs.push_back(rect); + + rect = new vpsc::Rectangle(266, 312, 730, 760); + rs.push_back(rect); + + rect = new vpsc::Rectangle(571, 617, 510, 540); + rs.push_back(rect); + + rect = new vpsc::Rectangle(414, 460, 521, 551); + rs.push_back(rect); + + rect = new vpsc::Rectangle(415, 461, 457, 487); + rs.push_back(rect); + + rect = new vpsc::Rectangle(73, 119, 846, 876); + rs.push_back(rect); + + rect = new vpsc::Rectangle(547, 593, 321, 351); + rs.push_back(rect); + + rect = new vpsc::Rectangle(258, 304, 174, 204); + rs.push_back(rect); + + rect = new vpsc::Rectangle(258, 304, 247, 277); + rs.push_back(rect); + + rect = new vpsc::Rectangle(550.5, 600.5, 304.5, 334.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(550.5, 600.5, 344.5, 374.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(621.5, 651.5, 473, 523); + rs.push_back(rect); + + rect = new vpsc::Rectangle(661.5, 691.5, 473, 523); + rs.push_back(rect); + + rect = new vpsc::Rectangle(470.5, 500.5, 108.5, 158.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(113, 163, 765.5, 795.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(113, 163, 805.5, 835.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(408, 458, 584.5, 614.5); + rs.push_back(rect); + + rect = new vpsc::Rectangle(614.5, 644.5, 843, 893); + rs.push_back(rect); + + AlignmentConstraint *alignment140664475503328 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475503328->addShape(0, 0); + alignment140664475503328->addShape(16, 0); + alignment140664475503328->addShape(18, 0); + alignment140664475503328->addShape(19, 0); + alignment140664475503328->addShape(26, 0); + alignment140664475503328->addShape(27, 0); + alignment140664475503328->addShape(41, 0); + alignment140664475503328->addShape(49, 0); + alignment140664475503328->addShape(50, 0); + alignment140664475503328->addShape(55, 0); + alignment140664475503328->addShape(56, 0); + alignment140664475503328->addShape(57, 0); + alignment140664475503328->addShape(58, 0); + alignment140664475503328->addShape(59, 0); + alignment140664475503328->addShape(63, 0); + alignment140664475503328->addShape(69, 0); + alignment140664475503328->addShape(89, 0); + ccs.push_back(alignment140664475503328); + + AlignmentConstraint *alignment140664481097440 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664481097440->addShape(1, 0); + alignment140664481097440->addShape(3, 0); + alignment140664481097440->addShape(46, 0); + alignment140664481097440->addShape(47, 0); + alignment140664481097440->addShape(84, 0); + ccs.push_back(alignment140664481097440); + + AlignmentConstraint *alignment140664483416688 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664483416688->addShape(2, 0); + alignment140664483416688->addShape(4, 0); + alignment140664483416688->addShape(65, 0); + alignment140664483416688->addShape(76, 0); + ccs.push_back(alignment140664483416688); + + AlignmentConstraint *alignment140664481096784 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664481096784->addShape(3, 0); + alignment140664481096784->addShape(46, 0); + alignment140664481096784->addShape(47, 0); + alignment140664481096784->addShape(84, 0); + ccs.push_back(alignment140664481096784); + + AlignmentConstraint *alignment140664475503952 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475503952->addShape(4, 0); + alignment140664475503952->addShape(65, 0); + alignment140664475503952->addShape(76, 0); + ccs.push_back(alignment140664475503952); + + AlignmentConstraint *alignment140664475504304 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475504304->addShape(7, 0); + alignment140664475504304->addShape(64, 0); + alignment140664475504304->addShape(66, 0); + alignment140664475504304->addShape(74, 0); + ccs.push_back(alignment140664475504304); + + AlignmentConstraint *alignment140664475504496 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475504496->addShape(8, 0); + alignment140664475504496->addShape(79, 0); + ccs.push_back(alignment140664475504496); + + AlignmentConstraint *alignment140664475504720 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475504720->addShape(9, 0); + alignment140664475504720->addShape(77, 0); + alignment140664475504720->addShape(87, 0); + alignment140664475504720->addShape(88, 0); + ccs.push_back(alignment140664475504720); + + AlignmentConstraint *alignment140664483418000 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664483418000->addShape(10, 0); + alignment140664483418000->addShape(11, 0); + ccs.push_back(alignment140664483418000); + + AlignmentConstraint *alignment140664483418368 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664483418368->addShape(11, 0); + ccs.push_back(alignment140664483418368); + + AlignmentConstraint *alignment140664483418496 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664483418496->addShape(12, 0); + ccs.push_back(alignment140664483418496); + + AlignmentConstraint *alignment140664483418656 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664483418656->addShape(13, 0); + alignment140664483418656->addShape(68, 0); + ccs.push_back(alignment140664483418656); + + AlignmentConstraint *alignment140664483418880 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664483418880->addShape(14, 0); + ccs.push_back(alignment140664483418880); + + AlignmentConstraint *alignment140664483419008 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664483419008->addShape(16, 0); + alignment140664483419008->addShape(18, 0); + alignment140664483419008->addShape(19, 0); + alignment140664483419008->addShape(26, 0); + alignment140664483419008->addShape(27, 0); + alignment140664483419008->addShape(41, 0); + alignment140664483419008->addShape(49, 0); + alignment140664483419008->addShape(50, 0); + alignment140664483419008->addShape(55, 0); + alignment140664483419008->addShape(56, 0); + alignment140664483419008->addShape(57, 0); + alignment140664483419008->addShape(58, 0); + alignment140664483419008->addShape(59, 0); + alignment140664483419008->addShape(63, 0); + alignment140664483419008->addShape(69, 0); + alignment140664483419008->addShape(89, 0); + ccs.push_back(alignment140664483419008); + + AlignmentConstraint *alignment140664476991552 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476991552->addShape(18, 0); + alignment140664476991552->addShape(19, 0); + alignment140664476991552->addShape(26, 0); + alignment140664476991552->addShape(27, 0); + alignment140664476991552->addShape(41, 0); + alignment140664476991552->addShape(49, 0); + alignment140664476991552->addShape(50, 0); + alignment140664476991552->addShape(55, 0); + alignment140664476991552->addShape(56, 0); + alignment140664476991552->addShape(57, 0); + alignment140664476991552->addShape(58, 0); + alignment140664476991552->addShape(59, 0); + alignment140664476991552->addShape(63, 0); + alignment140664476991552->addShape(69, 0); + alignment140664476991552->addShape(89, 0); + ccs.push_back(alignment140664476991552); + + AlignmentConstraint *alignment140664476992272 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476992272->addShape(19, 0); + alignment140664476992272->addShape(26, 0); + alignment140664476992272->addShape(27, 0); + alignment140664476992272->addShape(41, 0); + alignment140664476992272->addShape(49, 0); + alignment140664476992272->addShape(50, 0); + alignment140664476992272->addShape(55, 0); + alignment140664476992272->addShape(56, 0); + alignment140664476992272->addShape(57, 0); + alignment140664476992272->addShape(58, 0); + alignment140664476992272->addShape(59, 0); + alignment140664476992272->addShape(63, 0); + alignment140664476992272->addShape(69, 0); + alignment140664476992272->addShape(89, 0); + ccs.push_back(alignment140664476992272); + + AlignmentConstraint *alignment140664476992960 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476992960->addShape(20, 0); + alignment140664476992960->addShape(23, 0); + ccs.push_back(alignment140664476992960); + + AlignmentConstraint *alignment140664476993456 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476993456->addShape(22, 0); + ccs.push_back(alignment140664476993456); + + AlignmentConstraint *alignment140664476993584 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476993584->addShape(23, 0); + ccs.push_back(alignment140664476993584); + + AlignmentConstraint *alignment140664476993744 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476993744->addShape(24, 0); + ccs.push_back(alignment140664476993744); + + AlignmentConstraint *alignment140664476993904 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476993904->addShape(25, 0); + alignment140664476993904->addShape(62, 0); + ccs.push_back(alignment140664476993904); + + AlignmentConstraint *alignment140664476994128 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476994128->addShape(26, 0); + alignment140664476994128->addShape(27, 0); + alignment140664476994128->addShape(41, 0); + alignment140664476994128->addShape(49, 0); + alignment140664476994128->addShape(50, 0); + alignment140664476994128->addShape(55, 0); + alignment140664476994128->addShape(56, 0); + alignment140664476994128->addShape(57, 0); + alignment140664476994128->addShape(58, 0); + alignment140664476994128->addShape(59, 0); + alignment140664476994128->addShape(63, 0); + alignment140664476994128->addShape(69, 0); + alignment140664476994128->addShape(89, 0); + ccs.push_back(alignment140664476994128); + + AlignmentConstraint *alignment140664476994608 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476994608->addShape(27, 0); + alignment140664476994608->addShape(41, 0); + alignment140664476994608->addShape(49, 0); + alignment140664476994608->addShape(50, 0); + alignment140664476994608->addShape(55, 0); + alignment140664476994608->addShape(56, 0); + alignment140664476994608->addShape(57, 0); + alignment140664476994608->addShape(58, 0); + alignment140664476994608->addShape(59, 0); + alignment140664476994608->addShape(63, 0); + alignment140664476994608->addShape(69, 0); + alignment140664476994608->addShape(89, 0); + ccs.push_back(alignment140664476994608); + + AlignmentConstraint *alignment140664476995232 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476995232->addShape(28, 0); + ccs.push_back(alignment140664476995232); + + AlignmentConstraint *alignment140664476995392 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476995392->addShape(29, 0); + alignment140664476995392->addShape(30, 0); + alignment140664476995392->addShape(34, 0); + alignment140664476995392->addShape(35, 0); + ccs.push_back(alignment140664476995392); + + AlignmentConstraint *alignment140664476995616 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476995616->addShape(30, 0); + alignment140664476995616->addShape(34, 0); + alignment140664476995616->addShape(35, 0); + ccs.push_back(alignment140664476995616); + + AlignmentConstraint *alignment140664476995888 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476995888->addShape(31, 0); + ccs.push_back(alignment140664476995888); + + AlignmentConstraint *alignment140664476996016 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476996016->addShape(32, 0); + ccs.push_back(alignment140664476996016); + + AlignmentConstraint *alignment140664476996176 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476996176->addShape(33, 0); + alignment140664476996176->addShape(44, 0); + alignment140664476996176->addShape(45, 0); + alignment140664476996176->addShape(51, 0); + alignment140664476996176->addShape(52, 0); + ccs.push_back(alignment140664476996176); + + AlignmentConstraint *alignment140664476996480 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476996480->addShape(34, 0); + alignment140664476996480->addShape(35, 0); + ccs.push_back(alignment140664476996480); + + AlignmentConstraint *alignment140664476996704 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476996704->addShape(35, 0); + ccs.push_back(alignment140664476996704); + + AlignmentConstraint *alignment140664476996832 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476996832->addShape(36, 0); + alignment140664476996832->addShape(61, 0); + ccs.push_back(alignment140664476996832); + + AlignmentConstraint *alignment140664476997056 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476997056->addShape(37, 0); + alignment140664476997056->addShape(38, 0); + ccs.push_back(alignment140664476997056); + + AlignmentConstraint *alignment140664476993184 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476993184->addShape(38, 0); + ccs.push_back(alignment140664476993184); + + AlignmentConstraint *alignment140664476993312 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476993312->addShape(40, 0); + ccs.push_back(alignment140664476993312); + + AlignmentConstraint *alignment140664476997808 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476997808->addShape(41, 0); + alignment140664476997808->addShape(49, 0); + alignment140664476997808->addShape(50, 0); + alignment140664476997808->addShape(55, 0); + alignment140664476997808->addShape(56, 0); + alignment140664476997808->addShape(57, 0); + alignment140664476997808->addShape(58, 0); + alignment140664476997808->addShape(59, 0); + alignment140664476997808->addShape(63, 0); + alignment140664476997808->addShape(69, 0); + alignment140664476997808->addShape(89, 0); + ccs.push_back(alignment140664476997808); + + AlignmentConstraint *alignment140664476998480 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476998480->addShape(42, 0); + alignment140664476998480->addShape(43, 0); + alignment140664476998480->addShape(92, 0); + alignment140664476998480->addShape(93, 0); + ccs.push_back(alignment140664476998480); + + AlignmentConstraint *alignment140664476998704 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476998704->addShape(43, 0); + alignment140664476998704->addShape(92, 0); + alignment140664476998704->addShape(93, 0); + ccs.push_back(alignment140664476998704); + + AlignmentConstraint *alignment140664476998976 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476998976->addShape(44, 0); + alignment140664476998976->addShape(45, 0); + alignment140664476998976->addShape(51, 0); + alignment140664476998976->addShape(52, 0); + ccs.push_back(alignment140664476998976); + + AlignmentConstraint *alignment140664476999216 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476999216->addShape(45, 0); + alignment140664476999216->addShape(51, 0); + alignment140664476999216->addShape(52, 0); + ccs.push_back(alignment140664476999216); + + AlignmentConstraint *alignment140664476999488 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476999488->addShape(46, 0); + alignment140664476999488->addShape(47, 0); + alignment140664476999488->addShape(84, 0); + ccs.push_back(alignment140664476999488); + + AlignmentConstraint *alignment140664476999728 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476999728->addShape(47, 0); + alignment140664476999728->addShape(84, 0); + ccs.push_back(alignment140664476999728); + + AlignmentConstraint *alignment140664476999920 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476999920->addShape(48, 0); + ccs.push_back(alignment140664476999920); + + AlignmentConstraint *alignment140664477000048 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477000048->addShape(49, 0); + alignment140664477000048->addShape(50, 0); + alignment140664477000048->addShape(55, 0); + alignment140664477000048->addShape(56, 0); + alignment140664477000048->addShape(57, 0); + alignment140664477000048->addShape(58, 0); + alignment140664477000048->addShape(59, 0); + alignment140664477000048->addShape(63, 0); + alignment140664477000048->addShape(69, 0); + alignment140664477000048->addShape(89, 0); + ccs.push_back(alignment140664477000048); + + AlignmentConstraint *alignment140664477000656 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477000656->addShape(50, 0); + alignment140664477000656->addShape(55, 0); + alignment140664477000656->addShape(56, 0); + alignment140664477000656->addShape(57, 0); + alignment140664477000656->addShape(58, 0); + alignment140664477000656->addShape(59, 0); + alignment140664477000656->addShape(63, 0); + alignment140664477000656->addShape(69, 0); + alignment140664477000656->addShape(89, 0); + ccs.push_back(alignment140664477000656); + + AlignmentConstraint *alignment140664477001184 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477001184->addShape(51, 0); + alignment140664477001184->addShape(52, 0); + ccs.push_back(alignment140664477001184); + + AlignmentConstraint *alignment140664477001408 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477001408->addShape(52, 0); + ccs.push_back(alignment140664477001408); + + AlignmentConstraint *alignment140664477001536 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477001536->addShape(53, 0); + alignment140664477001536->addShape(54, 0); + ccs.push_back(alignment140664477001536); + + AlignmentConstraint *alignment140664477001760 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477001760->addShape(54, 0); + ccs.push_back(alignment140664477001760); + + AlignmentConstraint *alignment140664477001888 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477001888->addShape(55, 0); + alignment140664477001888->addShape(56, 0); + alignment140664477001888->addShape(57, 0); + alignment140664477001888->addShape(58, 0); + alignment140664477001888->addShape(59, 0); + alignment140664477001888->addShape(63, 0); + alignment140664477001888->addShape(69, 0); + alignment140664477001888->addShape(89, 0); + ccs.push_back(alignment140664477001888); + + AlignmentConstraint *alignment140664477002240 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477002240->addShape(56, 0); + alignment140664477002240->addShape(57, 0); + alignment140664477002240->addShape(58, 0); + alignment140664477002240->addShape(59, 0); + alignment140664477002240->addShape(63, 0); + alignment140664477002240->addShape(69, 0); + alignment140664477002240->addShape(89, 0); + ccs.push_back(alignment140664477002240); + + AlignmentConstraint *alignment140664477002640 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477002640->addShape(57, 0); + alignment140664477002640->addShape(58, 0); + alignment140664477002640->addShape(59, 0); + alignment140664477002640->addShape(63, 0); + alignment140664477002640->addShape(69, 0); + alignment140664477002640->addShape(89, 0); + ccs.push_back(alignment140664477002640); + + AlignmentConstraint *alignment140664477003008 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477003008->addShape(58, 0); + alignment140664477003008->addShape(59, 0); + alignment140664477003008->addShape(63, 0); + alignment140664477003008->addShape(69, 0); + alignment140664477003008->addShape(89, 0); + ccs.push_back(alignment140664477003008); + + AlignmentConstraint *alignment140664477003344 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477003344->addShape(59, 0); + alignment140664477003344->addShape(63, 0); + alignment140664477003344->addShape(69, 0); + alignment140664477003344->addShape(89, 0); + ccs.push_back(alignment140664477003344); + + AlignmentConstraint *alignment140664477003568 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477003568->addShape(60, 0); + ccs.push_back(alignment140664477003568); + + AlignmentConstraint *alignment140664477003728 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477003728->addShape(61, 0); + ccs.push_back(alignment140664477003728); + + AlignmentConstraint *alignment140664477003888 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477003888->addShape(62, 0); + ccs.push_back(alignment140664477003888); + + AlignmentConstraint *alignment140664477004048 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477004048->addShape(63, 0); + alignment140664477004048->addShape(69, 0); + alignment140664477004048->addShape(89, 0); + ccs.push_back(alignment140664477004048); + + AlignmentConstraint *alignment140664477004320 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477004320->addShape(64, 0); + alignment140664477004320->addShape(66, 0); + alignment140664477004320->addShape(74, 0); + ccs.push_back(alignment140664477004320); + + AlignmentConstraint *alignment140664477004560 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477004560->addShape(65, 0); + alignment140664477004560->addShape(76, 0); + ccs.push_back(alignment140664477004560); + + AlignmentConstraint *alignment140664477004752 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477004752->addShape(66, 0); + alignment140664477004752->addShape(74, 0); + ccs.push_back(alignment140664477004752); + + AlignmentConstraint *alignment140664477004944 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477004944->addShape(67, 0); + ccs.push_back(alignment140664477004944); + + AlignmentConstraint *alignment140664477005072 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477005072->addShape(68, 0); + ccs.push_back(alignment140664477005072); + + AlignmentConstraint *alignment140664477005232 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477005232->addShape(69, 0); + alignment140664477005232->addShape(89, 0); + ccs.push_back(alignment140664477005232); + + AlignmentConstraint *alignment140664477005456 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477005456->addShape(70, 0); + alignment140664477005456->addShape(73, 0); + ccs.push_back(alignment140664477005456); + + AlignmentConstraint *alignment140664477005648 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664477005648->addShape(71, 0); + alignment140664477005648->addShape(72, 0); + ccs.push_back(alignment140664477005648); + + AlignmentConstraint *alignment140664476997248 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476997248->addShape(72, 0); + ccs.push_back(alignment140664476997248); + + AlignmentConstraint *alignment140664476997376 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476997376->addShape(73, 0); + ccs.push_back(alignment140664476997376); + + AlignmentConstraint *alignment140664476997536 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664476997536->addShape(74, 0); + ccs.push_back(alignment140664476997536); + + AlignmentConstraint *alignment140664475640112 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475640112->addShape(76, 0); + ccs.push_back(alignment140664475640112); + + AlignmentConstraint *alignment140664475640272 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475640272->addShape(77, 0); + alignment140664475640272->addShape(87, 0); + alignment140664475640272->addShape(88, 0); + ccs.push_back(alignment140664475640272); + + AlignmentConstraint *alignment140664475640544 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475640544->addShape(78, 0); + ccs.push_back(alignment140664475640544); + + AlignmentConstraint *alignment140664475640672 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475640672->addShape(79, 0); + ccs.push_back(alignment140664475640672); + + AlignmentConstraint *alignment140664475640832 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475640832->addShape(81, 0); + alignment140664475640832->addShape(91, 0); + ccs.push_back(alignment140664475640832); + + AlignmentConstraint *alignment140664475641056 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475641056->addShape(82, 0); + ccs.push_back(alignment140664475641056); + + AlignmentConstraint *alignment140664475641184 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475641184->addShape(83, 0); + ccs.push_back(alignment140664475641184); + + AlignmentConstraint *alignment140664475641344 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475641344->addShape(84, 0); + ccs.push_back(alignment140664475641344); + + AlignmentConstraint *alignment140664475641504 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475641504->addShape(85, 0); + ccs.push_back(alignment140664475641504); + + AlignmentConstraint *alignment140664475641664 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475641664->addShape(86, 0); + ccs.push_back(alignment140664475641664); + + AlignmentConstraint *alignment140664475641824 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475641824->addShape(87, 0); + alignment140664475641824->addShape(88, 0); + ccs.push_back(alignment140664475641824); + + AlignmentConstraint *alignment140664475642048 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475642048->addShape(88, 0); + ccs.push_back(alignment140664475642048); + + AlignmentConstraint *alignment140664475642176 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475642176->addShape(89, 0); + ccs.push_back(alignment140664475642176); + + AlignmentConstraint *alignment140664475642336 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475642336->addShape(90, 0); + ccs.push_back(alignment140664475642336); + + AlignmentConstraint *alignment140664475642496 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475642496->addShape(91, 0); + ccs.push_back(alignment140664475642496); + + AlignmentConstraint *alignment140664475642656 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475642656->addShape(92, 0); + alignment140664475642656->addShape(93, 0); + ccs.push_back(alignment140664475642656); + + AlignmentConstraint *alignment140664475642880 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475642880->addShape(93, 0); + ccs.push_back(alignment140664475642880); + + SeparationConstraint *separation140664475644192 = new SeparationConstraint(vpsc::XDIM, alignment140664475642336, alignment140664476997376, 36, false); + ccs.push_back(separation140664475644192); + + SeparationConstraint *separation140664481097840 = new SeparationConstraint(vpsc::XDIM, alignment140664476997376, alignment140664475640112, 14, false); + ccs.push_back(separation140664481097840); + + SeparationConstraint *separation140664476990640 = new SeparationConstraint(vpsc::XDIM, alignment140664475640112, alignment140664477001408, 35, false); + ccs.push_back(separation140664476990640); + + SeparationConstraint *separation140664481098032 = new SeparationConstraint(vpsc::XDIM, alignment140664477001408, alignment140664475640544, 23, false); + ccs.push_back(separation140664481098032); + + SeparationConstraint *separation140664481098176 = new SeparationConstraint(vpsc::XDIM, alignment140664475640544, alignment140664483418656, 7, false); + ccs.push_back(separation140664481098176); + + SeparationConstraint *separation140664481098320 = new SeparationConstraint(vpsc::XDIM, alignment140664477005072, alignment140664476996704, 21, false); + ccs.push_back(separation140664481098320); + + SeparationConstraint *separation140664481098496 = new SeparationConstraint(vpsc::XDIM, alignment140664476996704, alignment140664476997248, 6, false); + ccs.push_back(separation140664481098496); + + SeparationConstraint *separation140664481098672 = new SeparationConstraint(vpsc::XDIM, alignment140664476997248, alignment140664476993312, 23, false); + ccs.push_back(separation140664481098672); + + SeparationConstraint *separation140664476989584 = new SeparationConstraint(vpsc::XDIM, alignment140664476993312, alignment140664477004944, 3, false); + ccs.push_back(separation140664476989584); + + SeparationConstraint *separation140664476989760 = new SeparationConstraint(vpsc::XDIM, alignment140664477004944, alignment140664475642880, 16, false); + ccs.push_back(separation140664476989760); + + SeparationConstraint *separation140664476989936 = new SeparationConstraint(vpsc::XDIM, alignment140664475642880, alignment140664475641344, 8, false); + ccs.push_back(separation140664476989936); + + SeparationConstraint *separation140664476990112 = new SeparationConstraint(vpsc::XDIM, alignment140664476999488, alignment140664476996016, 16.6667, false); + ccs.push_back(separation140664476990112); + + SeparationConstraint *separation140664476990288 = new SeparationConstraint(vpsc::XDIM, alignment140664476996016, alignment140664477003728, 7, false); + ccs.push_back(separation140664476990288); + + SeparationConstraint *separation140664476990464 = new SeparationConstraint(vpsc::XDIM, alignment140664476996832, alignment140664483418496, 4, false); + ccs.push_back(separation140664476990464); + + SeparationConstraint *separation140664475645632 = new SeparationConstraint(vpsc::XDIM, alignment140664483418496, alignment140664477001760, 13, false); + ccs.push_back(separation140664475645632); + + SeparationConstraint *separation140664475645808 = new SeparationConstraint(vpsc::XDIM, alignment140664477001760, alignment140664476993184, 11, false); + ccs.push_back(separation140664475645808); + + SeparationConstraint *separation140664475645984 = new SeparationConstraint(vpsc::XDIM, alignment140664476993184, alignment140664476995888, 14, false); + ccs.push_back(separation140664475645984); + + SeparationConstraint *separation140664475646160 = new SeparationConstraint(vpsc::XDIM, alignment140664476995888, alignment140664476997536, 21, false); + ccs.push_back(separation140664475646160); + + SeparationConstraint *separation140664475646336 = new SeparationConstraint(vpsc::XDIM, alignment140664476997536, alignment140664476995232, 7, false); + ccs.push_back(separation140664475646336); + + SeparationConstraint *separation140664475646512 = new SeparationConstraint(vpsc::XDIM, alignment140664476995232, alignment140664475641664, 13, false); + ccs.push_back(separation140664475646512); + + SeparationConstraint *separation140664475646688 = new SeparationConstraint(vpsc::XDIM, alignment140664475641664, alignment140664476993456, 5, false); + ccs.push_back(separation140664475646688); + + SeparationConstraint *separation140664475646864 = new SeparationConstraint(vpsc::XDIM, alignment140664476993456, alignment140664476993744, 5, false); + ccs.push_back(separation140664475646864); + + SeparationConstraint *separation140664475647040 = new SeparationConstraint(vpsc::XDIM, alignment140664476993744, alignment140664483418368, 23, false); + ccs.push_back(separation140664475647040); + + SeparationConstraint *separation140664475647216 = new SeparationConstraint(vpsc::XDIM, alignment140664483418368, alignment140664475641824, 6.5, false); + ccs.push_back(separation140664475647216); + + SeparationConstraint *separation140664475647392 = new SeparationConstraint(vpsc::XDIM, alignment140664475504720, alignment140664476993584, 19.75, false); + ccs.push_back(separation140664475647392); + + SeparationConstraint *separation140664475647568 = new SeparationConstraint(vpsc::XDIM, alignment140664476993584, alignment140664475642176, 25, false); + ccs.push_back(separation140664475647568); + + SeparationConstraint *separation140664475647744 = new SeparationConstraint(vpsc::XDIM, alignment140664475642176, alignment140664475640672, 4, false); + ccs.push_back(separation140664475647744); + + SeparationConstraint *separation140664475647920 = new SeparationConstraint(vpsc::XDIM, alignment140664475640672, alignment140664475642496, 21, false); + ccs.push_back(separation140664475647920); + + SeparationConstraint *separation140664475648096 = new SeparationConstraint(vpsc::XDIM, alignment140664475642496, alignment140664475641504, 24, false); + ccs.push_back(separation140664475648096); + + SeparationConstraint *separation140664475648272 = new SeparationConstraint(vpsc::XDIM, alignment140664475641504, alignment140664477003888, 18, false); + ccs.push_back(separation140664475648272); + + SeparationConstraint *separation140664475648448 = new SeparationConstraint(vpsc::XDIM, alignment140664476993904, alignment140664475641184, 4, false); + ccs.push_back(separation140664475648448); + + SeparationConstraint *separation140664475648624 = new SeparationConstraint(vpsc::XDIM, alignment140664475641184, alignment140664483418880, 3, false); + ccs.push_back(separation140664475648624); + + SeparationConstraint *separation140664475648800 = new SeparationConstraint(vpsc::XDIM, alignment140664483418880, alignment140664475641056, 24, false); + ccs.push_back(separation140664475648800); + + SeparationConstraint *separation140664475648976 = new SeparationConstraint(vpsc::XDIM, alignment140664475641056, alignment140664476999920, 19, false); + ccs.push_back(separation140664475648976); + + SeparationConstraint *separation140664475649152 = new SeparationConstraint(vpsc::XDIM, alignment140664476999920, alignment140664477003568, 26, false); + ccs.push_back(separation140664475649152); + + AlignmentConstraint *alignment140664475649328 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475649328->addShape(0, 0); + ccs.push_back(alignment140664475649328); + + AlignmentConstraint *alignment140664475649488 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475649488->addShape(1, 0); + alignment140664475649488->addShape(8, 0); + alignment140664475649488->addShape(9, 0); + ccs.push_back(alignment140664475649488); + + AlignmentConstraint *alignment140664475649760 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475649760->addShape(2, 0); + alignment140664475649760->addShape(7, 0); + alignment140664475649760->addShape(90, 0); + ccs.push_back(alignment140664475649760); + + AlignmentConstraint *alignment140664475650000 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475650000->addShape(3, 0); + alignment140664475650000->addShape(77, 0); + alignment140664475650000->addShape(79, 0); + ccs.push_back(alignment140664475650000); + + AlignmentConstraint *alignment140664475650240 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475650240->addShape(4, 0); + alignment140664475650240->addShape(62, 0); + alignment140664475650240->addShape(66, 0); + ccs.push_back(alignment140664475650240); + + AlignmentConstraint *alignment140664475650480 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475650480->addShape(7, 0); + alignment140664475650480->addShape(90, 0); + ccs.push_back(alignment140664475650480); + + AlignmentConstraint *alignment140664475650672 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475650672->addShape(8, 0); + alignment140664475650672->addShape(9, 0); + ccs.push_back(alignment140664475650672); + + AlignmentConstraint *alignment140664475650864 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475650864->addShape(9, 0); + ccs.push_back(alignment140664475650864); + + AlignmentConstraint *alignment140664475639072 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475639072->addShape(10, 0); + ccs.push_back(alignment140664475639072); + + AlignmentConstraint *alignment140664475639232 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475639232->addShape(11, 0); + ccs.push_back(alignment140664475639232); + + AlignmentConstraint *alignment140664475639392 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475639392->addShape(12, 0); + alignment140664475639392->addShape(13, 0); + alignment140664475639392->addShape(14, 0); + alignment140664475639392->addShape(60, 0); + alignment140664475639392->addShape(63, 0); + alignment140664475639392->addShape(64, 0); + alignment140664475639392->addShape(65, 0); + alignment140664475639392->addShape(67, 0); + ccs.push_back(alignment140664475639392); + + AlignmentConstraint *alignment140664475639872 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475639872->addShape(13, 0); + alignment140664475639872->addShape(14, 0); + alignment140664475639872->addShape(60, 0); + alignment140664475639872->addShape(63, 0); + alignment140664475639872->addShape(64, 0); + alignment140664475639872->addShape(65, 0); + alignment140664475639872->addShape(67, 0); + ccs.push_back(alignment140664475639872); + + AlignmentConstraint *alignment140664475653264 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475653264->addShape(14, 0); + alignment140664475653264->addShape(60, 0); + alignment140664475653264->addShape(63, 0); + alignment140664475653264->addShape(64, 0); + alignment140664475653264->addShape(65, 0); + alignment140664475653264->addShape(67, 0); + ccs.push_back(alignment140664475653264); + + AlignmentConstraint *alignment140664475653632 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475653632->addShape(16, 0); + ccs.push_back(alignment140664475653632); + + AlignmentConstraint *alignment140664475653792 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475653792->addShape(18, 0); + ccs.push_back(alignment140664475653792); + + AlignmentConstraint *alignment140664475653952 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475653952->addShape(19, 0); + ccs.push_back(alignment140664475653952); + + AlignmentConstraint *alignment140664475654112 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475654112->addShape(20, 0); + alignment140664475654112->addShape(81, 0); + ccs.push_back(alignment140664475654112); + + AlignmentConstraint *alignment140664475654336 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475654336->addShape(22, 0); + alignment140664475654336->addShape(53, 0); + alignment140664475654336->addShape(89, 0); + ccs.push_back(alignment140664475654336); + + AlignmentConstraint *alignment140664475654528 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475654528->addShape(23, 0); + alignment140664475654528->addShape(24, 0); + alignment140664475654528->addShape(91, 0); + ccs.push_back(alignment140664475654528); + + AlignmentConstraint *alignment140664475654720 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475654720->addShape(24, 0); + alignment140664475654720->addShape(91, 0); + ccs.push_back(alignment140664475654720); + + AlignmentConstraint *alignment140664475654912 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475654912->addShape(25, 0); + alignment140664475654912->addShape(48, 0); + ccs.push_back(alignment140664475654912); + + AlignmentConstraint *alignment140664475655104 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475655104->addShape(26, 0); + alignment140664475655104->addShape(31, 0); + alignment140664475655104->addShape(32, 0); + alignment140664475655104->addShape(33, 0); + ccs.push_back(alignment140664475655104); + + AlignmentConstraint *alignment140664475655344 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475655344->addShape(27, 0); + ccs.push_back(alignment140664475655344); + + AlignmentConstraint *alignment140664475655504 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475655504->addShape(28, 0); + alignment140664475655504->addShape(52, 0); + alignment140664475655504->addShape(54, 0); + alignment140664475655504->addShape(56, 0); + ccs.push_back(alignment140664475655504); + + AlignmentConstraint *alignment140664475655776 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475655776->addShape(29, 0); + alignment140664475655776->addShape(43, 0); + ccs.push_back(alignment140664475655776); + + AlignmentConstraint *alignment140664475656000 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475656000->addShape(30, 0); + alignment140664475656000->addShape(93, 0); + ccs.push_back(alignment140664475656000); + + AlignmentConstraint *alignment140664475656192 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475656192->addShape(31, 0); + alignment140664475656192->addShape(32, 0); + alignment140664475656192->addShape(33, 0); + ccs.push_back(alignment140664475656192); + + AlignmentConstraint *alignment140664475656432 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475656432->addShape(32, 0); + alignment140664475656432->addShape(33, 0); + ccs.push_back(alignment140664475656432); + + AlignmentConstraint *alignment140664475656624 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475656624->addShape(33, 0); + ccs.push_back(alignment140664475656624); + + AlignmentConstraint *alignment140664475656752 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475656752->addShape(34, 0); + alignment140664475656752->addShape(92, 0); + ccs.push_back(alignment140664475656752); + + AlignmentConstraint *alignment140664475656976 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475656976->addShape(35, 0); + alignment140664475656976->addShape(42, 0); + ccs.push_back(alignment140664475656976); + + AlignmentConstraint *alignment140664475657168 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475657168->addShape(36, 0); + ccs.push_back(alignment140664475657168); + + AlignmentConstraint *alignment140664475657296 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475657296->addShape(37, 0); + ccs.push_back(alignment140664475657296); + + AlignmentConstraint *alignment140664475657456 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475657456->addShape(38, 0); + ccs.push_back(alignment140664475657456); + + AlignmentConstraint *alignment140664475657616 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475657616->addShape(40, 0); + alignment140664475657616->addShape(61, 0); + alignment140664475657616->addShape(68, 0); + ccs.push_back(alignment140664475657616); + + AlignmentConstraint *alignment140664475657888 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475657888->addShape(41, 0); + alignment140664475657888->addShape(86, 0); + ccs.push_back(alignment140664475657888); + + AlignmentConstraint *alignment140664475658080 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475658080->addShape(42, 0); + ccs.push_back(alignment140664475658080); + + AlignmentConstraint *alignment140664475658208 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475658208->addShape(43, 0); + ccs.push_back(alignment140664475658208); + + AlignmentConstraint *alignment140664475658368 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475658368->addShape(44, 0); + alignment140664475658368->addShape(46, 0); + alignment140664475658368->addShape(70, 0); + alignment140664475658368->addShape(71, 0); + ccs.push_back(alignment140664475658368); + + AlignmentConstraint *alignment140664475658640 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475658640->addShape(45, 0); + alignment140664475658640->addShape(47, 0); + alignment140664475658640->addShape(72, 0); + alignment140664475658640->addShape(73, 0); + ccs.push_back(alignment140664475658640); + + AlignmentConstraint *alignment140664475658912 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475658912->addShape(46, 0); + alignment140664475658912->addShape(70, 0); + alignment140664475658912->addShape(71, 0); + ccs.push_back(alignment140664475658912); + + AlignmentConstraint *alignment140664475659184 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475659184->addShape(47, 0); + alignment140664475659184->addShape(72, 0); + alignment140664475659184->addShape(73, 0); + ccs.push_back(alignment140664475659184); + + AlignmentConstraint *alignment140664475659424 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475659424->addShape(48, 0); + ccs.push_back(alignment140664475659424); + + AlignmentConstraint *alignment140664475659552 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475659552->addShape(49, 0); + ccs.push_back(alignment140664475659552); + + AlignmentConstraint *alignment140664475659712 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475659712->addShape(50, 0); + ccs.push_back(alignment140664475659712); + + AlignmentConstraint *alignment140664475659872 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475659872->addShape(51, 0); + alignment140664475659872->addShape(55, 0); + ccs.push_back(alignment140664475659872); + + AlignmentConstraint *alignment140664475660096 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475660096->addShape(52, 0); + alignment140664475660096->addShape(54, 0); + alignment140664475660096->addShape(56, 0); + ccs.push_back(alignment140664475660096); + + AlignmentConstraint *alignment140664475660336 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475660336->addShape(53, 0); + alignment140664475660336->addShape(89, 0); + ccs.push_back(alignment140664475660336); + + AlignmentConstraint *alignment140664475660528 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475660528->addShape(54, 0); + alignment140664475660528->addShape(56, 0); + ccs.push_back(alignment140664475660528); + + AlignmentConstraint *alignment140664475660720 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475660720->addShape(55, 0); + ccs.push_back(alignment140664475660720); + + AlignmentConstraint *alignment140664475660848 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475660848->addShape(56, 0); + ccs.push_back(alignment140664475660848); + + AlignmentConstraint *alignment140664475661008 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475661008->addShape(57, 0); + alignment140664475661008->addShape(76, 0); + ccs.push_back(alignment140664475661008); + + AlignmentConstraint *alignment140664475661232 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475661232->addShape(58, 0); + ccs.push_back(alignment140664475661232); + + AlignmentConstraint *alignment140664475661360 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475661360->addShape(59, 0); + alignment140664475661360->addShape(88, 0); + ccs.push_back(alignment140664475661360); + + AlignmentConstraint *alignment140664475661584 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475661584->addShape(60, 0); + alignment140664475661584->addShape(63, 0); + alignment140664475661584->addShape(64, 0); + alignment140664475661584->addShape(65, 0); + alignment140664475661584->addShape(67, 0); + ccs.push_back(alignment140664475661584); + + AlignmentConstraint *alignment140664475661936 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475661936->addShape(61, 0); + alignment140664475661936->addShape(68, 0); + ccs.push_back(alignment140664475661936); + + AlignmentConstraint *alignment140664475662160 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475662160->addShape(62, 0); + alignment140664475662160->addShape(66, 0); + ccs.push_back(alignment140664475662160); + + AlignmentConstraint *alignment140664475662352 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475662352->addShape(63, 0); + alignment140664475662352->addShape(64, 0); + alignment140664475662352->addShape(65, 0); + alignment140664475662352->addShape(67, 0); + ccs.push_back(alignment140664475662352); + + AlignmentConstraint *alignment140664475662544 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475662544->addShape(64, 0); + alignment140664475662544->addShape(65, 0); + alignment140664475662544->addShape(67, 0); + ccs.push_back(alignment140664475662544); + + AlignmentConstraint *alignment140664475662816 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475662816->addShape(65, 0); + alignment140664475662816->addShape(67, 0); + ccs.push_back(alignment140664475662816); + + AlignmentConstraint *alignment140664475663008 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475663008->addShape(66, 0); + ccs.push_back(alignment140664475663008); + + AlignmentConstraint *alignment140664475663136 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475663136->addShape(67, 0); + ccs.push_back(alignment140664475663136); + + AlignmentConstraint *alignment140664475663296 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475663296->addShape(68, 0); + ccs.push_back(alignment140664475663296); + + AlignmentConstraint *alignment140664475663456 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475663456->addShape(69, 0); + ccs.push_back(alignment140664475663456); + + AlignmentConstraint *alignment140664475663616 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475663616->addShape(70, 0); + alignment140664475663616->addShape(71, 0); + ccs.push_back(alignment140664475663616); + + AlignmentConstraint *alignment140664475663840 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475663840->addShape(71, 0); + ccs.push_back(alignment140664475663840); + + AlignmentConstraint *alignment140664475663968 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475663968->addShape(72, 0); + alignment140664475663968->addShape(73, 0); + ccs.push_back(alignment140664475663968); + + AlignmentConstraint *alignment140664475664192 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475664192->addShape(73, 0); + ccs.push_back(alignment140664475664192); + + AlignmentConstraint *alignment140664475664320 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475664320->addShape(74, 0); + ccs.push_back(alignment140664475664320); + + AlignmentConstraint *alignment140664475664480 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475664480->addShape(76, 0); + ccs.push_back(alignment140664475664480); + + AlignmentConstraint *alignment140664475664640 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475664640->addShape(77, 0); + alignment140664475664640->addShape(79, 0); + ccs.push_back(alignment140664475664640); + + AlignmentConstraint *alignment140664475664864 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475664864->addShape(78, 0); + ccs.push_back(alignment140664475664864); + + AlignmentConstraint *alignment140664475664992 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475664992->addShape(79, 0); + ccs.push_back(alignment140664475664992); + + AlignmentConstraint *alignment140664475665152 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475665152->addShape(81, 0); + ccs.push_back(alignment140664475665152); + + AlignmentConstraint *alignment140664475665312 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475665312->addShape(82, 0); + alignment140664475665312->addShape(85, 0); + ccs.push_back(alignment140664475665312); + + AlignmentConstraint *alignment140664475665536 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475665536->addShape(83, 0); + ccs.push_back(alignment140664475665536); + + AlignmentConstraint *alignment140664475665664 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475665664->addShape(84, 0); + ccs.push_back(alignment140664475665664); + + AlignmentConstraint *alignment140664475665824 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475665824->addShape(85, 0); + ccs.push_back(alignment140664475665824); + + AlignmentConstraint *alignment140664475665984 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475665984->addShape(86, 0); + ccs.push_back(alignment140664475665984); + + AlignmentConstraint *alignment140664475666144 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475666144->addShape(87, 0); + ccs.push_back(alignment140664475666144); + + AlignmentConstraint *alignment140664475666304 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475666304->addShape(88, 0); + ccs.push_back(alignment140664475666304); + + AlignmentConstraint *alignment140664475666464 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475666464->addShape(89, 0); + ccs.push_back(alignment140664475666464); + + AlignmentConstraint *alignment140664475666624 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475666624->addShape(90, 0); + ccs.push_back(alignment140664475666624); + + AlignmentConstraint *alignment140664475666784 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475666784->addShape(91, 0); + ccs.push_back(alignment140664475666784); + + AlignmentConstraint *alignment140664475666944 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475666944->addShape(92, 0); + ccs.push_back(alignment140664475666944); + + AlignmentConstraint *alignment140664475667104 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475667104->addShape(93, 0); + ccs.push_back(alignment140664475667104); + + SeparationConstraint *separation140664475667264 = new SeparationConstraint(vpsc::YDIM, alignment140664475657456, alignment140664475659552, 10, false); + ccs.push_back(separation140664475667264); + + SeparationConstraint *separation140664475667440 = new SeparationConstraint(vpsc::YDIM, alignment140664475659552, alignment140664475657296, 11, false); + ccs.push_back(separation140664475667440); + + SeparationConstraint *separation140664475667616 = new SeparationConstraint(vpsc::YDIM, alignment140664475657296, alignment140664475655344, 19, false); + ccs.push_back(separation140664475667616); + + SeparationConstraint *separation140664475667792 = new SeparationConstraint(vpsc::YDIM, alignment140664475655344, alignment140664475657168, 13, false); + ccs.push_back(separation140664475667792); + + SeparationConstraint *separation140664475667968 = new SeparationConstraint(vpsc::YDIM, alignment140664475657168, alignment140664475659424, 9, false); + ccs.push_back(separation140664475667968); + + SeparationConstraint *separation140664475668144 = new SeparationConstraint(vpsc::YDIM, alignment140664475654912, alignment140664475658080, 22.5, false); + ccs.push_back(separation140664475668144); + + SeparationConstraint *separation140664475668320 = new SeparationConstraint(vpsc::YDIM, alignment140664475658080, alignment140664475659872, 11, false); + ccs.push_back(separation140664475668320); + + SeparationConstraint *separation140664475668496 = new SeparationConstraint(vpsc::YDIM, alignment140664475660720, alignment140664475666944, 9, false); + ccs.push_back(separation140664475668496); + + SeparationConstraint *separation140664475668672 = new SeparationConstraint(vpsc::YDIM, alignment140664475666944, alignment140664475656624, 25, false); + ccs.push_back(separation140664475668672); + + SeparationConstraint *separation140664475668848 = new SeparationConstraint(vpsc::YDIM, alignment140664475655104, alignment140664475658208, 26.75, false); + ccs.push_back(separation140664475668848); + + SeparationConstraint *separation140664475669024 = new SeparationConstraint(vpsc::YDIM, alignment140664475658208, alignment140664475660096, 10.6667, false); + ccs.push_back(separation140664475669024); + + SeparationConstraint *separation140664475669200 = new SeparationConstraint(vpsc::YDIM, alignment140664475660848, alignment140664475667104, 9, false); + ccs.push_back(separation140664475669200); + + SeparationConstraint *separation140664475669376 = new SeparationConstraint(vpsc::YDIM, alignment140664475667104, alignment140664475666784, 24, false); + ccs.push_back(separation140664475669376); + + SeparationConstraint *separation140664475669552 = new SeparationConstraint(vpsc::YDIM, alignment140664475666784, alignment140664475663840, 23, false); + ccs.push_back(separation140664475669552); + + SeparationConstraint *separation140664475669728 = new SeparationConstraint(vpsc::YDIM, alignment140664475658368, alignment140664475663456, 13.75, false); + ccs.push_back(separation140664475669728); + + SeparationConstraint *separation140664475669904 = new SeparationConstraint(vpsc::YDIM, alignment140664475663456, alignment140664475664192, 12, false); + ccs.push_back(separation140664475669904); + + SeparationConstraint *separation140664475670080 = new SeparationConstraint(vpsc::YDIM, alignment140664475658640, alignment140664475649328, 18.75, false); + ccs.push_back(separation140664475670080); + + SeparationConstraint *separation140664475670256 = new SeparationConstraint(vpsc::YDIM, alignment140664475649328, alignment140664475666464, 44, false); + ccs.push_back(separation140664475670256); + + SeparationConstraint *separation140664475670432 = new SeparationConstraint(vpsc::YDIM, alignment140664475654336, alignment140664475665152, 35.3333, false); + ccs.push_back(separation140664475670432); + + SeparationConstraint *separation140664475670608 = new SeparationConstraint(vpsc::YDIM, alignment140664475665152, alignment140664475661360, 37, false); + ccs.push_back(separation140664475670608); + + SeparationConstraint *separation140664475670784 = new SeparationConstraint(vpsc::YDIM, alignment140664475666304, alignment140664475665824, 3, false); + ccs.push_back(separation140664475670784); + + SeparationConstraint *separation140664475670960 = new SeparationConstraint(vpsc::YDIM, alignment140664475665824, alignment140664475665536, 19, false); + ccs.push_back(separation140664475670960); + + SeparationConstraint *separation140664475671136 = new SeparationConstraint(vpsc::YDIM, alignment140664475665536, alignment140664475665984, 12, false); + ccs.push_back(separation140664475671136); + + SeparationConstraint *separation140664475671312 = new SeparationConstraint(vpsc::YDIM, alignment140664475665984, alignment140664475666144, 30, false); + ccs.push_back(separation140664475671312); + + SeparationConstraint *separation140664475671488 = new SeparationConstraint(vpsc::YDIM, alignment140664475666144, alignment140664475661232, 6, false); + ccs.push_back(separation140664475671488); + + SeparationConstraint *separation140664475671664 = new SeparationConstraint(vpsc::YDIM, alignment140664475661232, alignment140664475653952, 37, false); + ccs.push_back(separation140664475671664); + + SeparationConstraint *separation140664475508000 = new SeparationConstraint(vpsc::YDIM, alignment140664475653952, alignment140664475659712, 35, false); + ccs.push_back(separation140664475508000); + + SeparationConstraint *separation140664475508176 = new SeparationConstraint(vpsc::YDIM, alignment140664475659712, alignment140664475653792, 37, false); + ccs.push_back(separation140664475508176); + + SeparationConstraint *separation140664475508352 = new SeparationConstraint(vpsc::YDIM, alignment140664475653792, alignment140664475664480, 35, false); + ccs.push_back(separation140664475508352); + + SeparationConstraint *separation140664475508528 = new SeparationConstraint(vpsc::YDIM, alignment140664475664480, alignment140664475664864, 11, false); + ccs.push_back(separation140664475508528); + + SeparationConstraint *separation140664475508704 = new SeparationConstraint(vpsc::YDIM, alignment140664475664864, alignment140664475653632, 23, false); + ccs.push_back(separation140664475508704); + + SeparationConstraint *separation140664475508880 = new SeparationConstraint(vpsc::YDIM, alignment140664475653632, alignment140664475665664, 25, false); + ccs.push_back(separation140664475508880); + + SeparationConstraint *separation140664475509056 = new SeparationConstraint(vpsc::YDIM, alignment140664475665664, alignment140664475664320, 25, false); + ccs.push_back(separation140664475509056); + + SeparationConstraint *separation140664475509232 = new SeparationConstraint(vpsc::YDIM, alignment140664475664320, alignment140664475639232, 33, false); + ccs.push_back(separation140664475509232); + + SeparationConstraint *separation140664475509408 = new SeparationConstraint(vpsc::YDIM, alignment140664475639232, alignment140664475663136, 10, false); + ccs.push_back(separation140664475509408); + + SeparationConstraint *separation140664475509584 = new SeparationConstraint(vpsc::YDIM, alignment140664475639392, alignment140664475639072, 10.375, false); + ccs.push_back(separation140664475509584); + + SeparationConstraint *separation140664475509760 = new SeparationConstraint(vpsc::YDIM, alignment140664475639072, alignment140664475663296, 32, false); + ccs.push_back(separation140664475509760); + + SeparationConstraint *separation140664475509936 = new SeparationConstraint(vpsc::YDIM, alignment140664475657616, alignment140664475666624, 4.33333, false); + ccs.push_back(separation140664475509936); + + SeparationConstraint *separation140664475510112 = new SeparationConstraint(vpsc::YDIM, alignment140664475650480, alignment140664475650864, 31.5, false); + ccs.push_back(separation140664475510112); + + SeparationConstraint *separation140664475510288 = new SeparationConstraint(vpsc::YDIM, alignment140664475650864, alignment140664475663008, 10, false); + ccs.push_back(separation140664475510288); + + SeparationConstraint *separation140664475510464 = new SeparationConstraint(vpsc::YDIM, alignment140664475663008, alignment140664475664992, 11, false); + ccs.push_back(separation140664475510464); + + AlignmentConstraint *alignment140664475511088 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475511088->addShape(75, 0); + alignment140664475511088->addShape(75, 0); + ccs.push_back(alignment140664475511088); + + SeparationConstraint *separation140664475511312 = new SeparationConstraint(vpsc::YDIM, 75, 75, -50, true); + ccs.push_back(separation140664475511312); + + AlignmentConstraint *alignment140664475511456 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475511456->addShape(0, 0); + alignment140664475511456->addShape(94, 0); + ccs.push_back(alignment140664475511456); + + SeparationConstraint *separation140664475511680 = new SeparationConstraint(vpsc::XDIM, 0, 94, 62, true); + ccs.push_back(separation140664475511680); + + AlignmentConstraint *alignment140664475511824 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475511824->addShape(1, 0); + alignment140664475511824->addShape(95, 0); + ccs.push_back(alignment140664475511824); + + SeparationConstraint *separation140664475512048 = new SeparationConstraint(vpsc::YDIM, 1, 95, -50, true); + ccs.push_back(separation140664475512048); + + AlignmentConstraint *alignment140664475512192 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475512192->addShape(2, 0); + alignment140664475512192->addShape(96, 0); + ccs.push_back(alignment140664475512192); + + SeparationConstraint *separation140664475512416 = new SeparationConstraint(vpsc::XDIM, 2, 96, 62, true); + ccs.push_back(separation140664475512416); + + AlignmentConstraint *alignment140664475512560 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475512560->addShape(3, 0); + alignment140664475512560->addShape(97, 0); + ccs.push_back(alignment140664475512560); + + SeparationConstraint *separation140664475512784 = new SeparationConstraint(vpsc::YDIM, 3, 97, -50, true); + ccs.push_back(separation140664475512784); + + AlignmentConstraint *alignment140664475650992 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475650992->addShape(7, 0); + alignment140664475650992->addShape(98, 0); + ccs.push_back(alignment140664475650992); + + SeparationConstraint *separation140664475651216 = new SeparationConstraint(vpsc::XDIM, 7, 98, 62, true); + ccs.push_back(separation140664475651216); + + AlignmentConstraint *alignment140664475651360 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475651360->addShape(8, 0); + alignment140664475651360->addShape(99, 0); + ccs.push_back(alignment140664475651360); + + SeparationConstraint *separation140664475651584 = new SeparationConstraint(vpsc::YDIM, 8, 99, -50, true); + ccs.push_back(separation140664475651584); + + AlignmentConstraint *alignment140664475651728 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475651728->addShape(9, 0); + alignment140664475651728->addShape(100, 0); + ccs.push_back(alignment140664475651728); + + SeparationConstraint *separation140664475651952 = new SeparationConstraint(vpsc::YDIM, 9, 100, -50, true); + ccs.push_back(separation140664475651952); + + AlignmentConstraint *alignment140664475652096 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475652096->addShape(10, 0); + alignment140664475652096->addShape(101, 0); + ccs.push_back(alignment140664475652096); + + SeparationConstraint *separation140664475652320 = new SeparationConstraint(vpsc::XDIM, 10, 101, 62, true); + ccs.push_back(separation140664475652320); + + AlignmentConstraint *alignment140664475652464 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475652464->addShape(11, 0); + alignment140664475652464->addShape(102, 0); + ccs.push_back(alignment140664475652464); + + SeparationConstraint *separation140664475652688 = new SeparationConstraint(vpsc::XDIM, 11, 102, 62, true); + ccs.push_back(separation140664475652688); + + AlignmentConstraint *alignment140664475652832 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475652832->addShape(12, 0); + alignment140664475652832->addShape(103, 0); + ccs.push_back(alignment140664475652832); + + SeparationConstraint *separation140664475517040 = new SeparationConstraint(vpsc::XDIM, 12, 103, 62, true); + ccs.push_back(separation140664475517040); + + AlignmentConstraint *alignment140664475517184 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475517184->addShape(13, 0); + alignment140664475517184->addShape(104, 0); + ccs.push_back(alignment140664475517184); + + SeparationConstraint *separation140664475517408 = new SeparationConstraint(vpsc::YDIM, 13, 104, -50, true); + ccs.push_back(separation140664475517408); + + AlignmentConstraint *alignment140664475517552 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475517552->addShape(14, 0); + alignment140664475517552->addShape(105, 0); + ccs.push_back(alignment140664475517552); + + SeparationConstraint *separation140664475517776 = new SeparationConstraint(vpsc::YDIM, 14, 105, -50, true); + ccs.push_back(separation140664475517776); + + AlignmentConstraint *alignment140664475517920 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475517920->addShape(16, 0); + alignment140664475517920->addShape(106, 0); + ccs.push_back(alignment140664475517920); + + SeparationConstraint *separation140664475518144 = new SeparationConstraint(vpsc::XDIM, 16, 106, 62, true); + ccs.push_back(separation140664475518144); + + AlignmentConstraint *alignment140664475518288 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475518288->addShape(18, 0); + alignment140664475518288->addShape(107, 0); + ccs.push_back(alignment140664475518288); + + SeparationConstraint *separation140664475518512 = new SeparationConstraint(vpsc::XDIM, 18, 107, 62, true); + ccs.push_back(separation140664475518512); + + AlignmentConstraint *alignment140664475518656 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475518656->addShape(19, 0); + alignment140664475518656->addShape(108, 0); + ccs.push_back(alignment140664475518656); + + SeparationConstraint *separation140664475518880 = new SeparationConstraint(vpsc::XDIM, 19, 108, 62, true); + ccs.push_back(separation140664475518880); + + AlignmentConstraint *alignment140664475519024 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475519024->addShape(20, 0); + alignment140664475519024->addShape(109, 0); + ccs.push_back(alignment140664475519024); + + SeparationConstraint *separation140664475519248 = new SeparationConstraint(vpsc::XDIM, 20, 109, 62, true); + ccs.push_back(separation140664475519248); + + AlignmentConstraint *alignment140664475519392 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475519392->addShape(22, 0); + alignment140664475519392->addShape(110, 0); + ccs.push_back(alignment140664475519392); + + SeparationConstraint *separation140664475519616 = new SeparationConstraint(vpsc::YDIM, 22, 110, -50, true); + ccs.push_back(separation140664475519616); + + AlignmentConstraint *alignment140664475519760 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475519760->addShape(23, 0); + alignment140664475519760->addShape(111, 0); + ccs.push_back(alignment140664475519760); + + SeparationConstraint *separation140664475519984 = new SeparationConstraint(vpsc::XDIM, 23, 111, 62, true); + ccs.push_back(separation140664475519984); + + AlignmentConstraint *alignment140664475520128 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475520128->addShape(24, 0); + alignment140664475520128->addShape(112, 0); + ccs.push_back(alignment140664475520128); + + SeparationConstraint *separation140664475520352 = new SeparationConstraint(vpsc::YDIM, 24, 112, -50, true); + ccs.push_back(separation140664475520352); + + AlignmentConstraint *alignment140664475520496 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475520496->addShape(25, 0); + alignment140664475520496->addShape(113, 0); + ccs.push_back(alignment140664475520496); + + SeparationConstraint *separation140664475520720 = new SeparationConstraint(vpsc::YDIM, 25, 113, -50, true); + ccs.push_back(separation140664475520720); + + AlignmentConstraint *alignment140664475520864 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475520864->addShape(26, 0); + alignment140664475520864->addShape(114, 0); + ccs.push_back(alignment140664475520864); + + SeparationConstraint *separation140664475521088 = new SeparationConstraint(vpsc::XDIM, 26, 114, 62, true); + ccs.push_back(separation140664475521088); + + AlignmentConstraint *alignment140664475521232 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475521232->addShape(27, 0); + alignment140664475521232->addShape(115, 0); + ccs.push_back(alignment140664475521232); + + SeparationConstraint *separation140664475521456 = new SeparationConstraint(vpsc::XDIM, 27, 115, 62, true); + ccs.push_back(separation140664475521456); + + AlignmentConstraint *alignment140664475521600 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475521600->addShape(28, 0); + alignment140664475521600->addShape(116, 0); + ccs.push_back(alignment140664475521600); + + SeparationConstraint *separation140664475521824 = new SeparationConstraint(vpsc::YDIM, 28, 116, -50, true); + ccs.push_back(separation140664475521824); + + AlignmentConstraint *alignment140664475521968 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475521968->addShape(29, 0); + alignment140664475521968->addShape(117, 0); + ccs.push_back(alignment140664475521968); + + SeparationConstraint *separation140664475522192 = new SeparationConstraint(vpsc::YDIM, 29, 117, -50, true); + ccs.push_back(separation140664475522192); + + AlignmentConstraint *alignment140664475522336 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475522336->addShape(30, 0); + alignment140664475522336->addShape(118, 0); + ccs.push_back(alignment140664475522336); + + SeparationConstraint *separation140664475522560 = new SeparationConstraint(vpsc::YDIM, 30, 118, -50, true); + ccs.push_back(separation140664475522560); + + AlignmentConstraint *alignment140664475522704 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475522704->addShape(31, 0); + alignment140664475522704->addShape(119, 0); + ccs.push_back(alignment140664475522704); + + SeparationConstraint *separation140664475522928 = new SeparationConstraint(vpsc::XDIM, 31, 119, 62, true); + ccs.push_back(separation140664475522928); + + AlignmentConstraint *alignment140664475523072 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475523072->addShape(32, 0); + alignment140664475523072->addShape(120, 0); + ccs.push_back(alignment140664475523072); + + SeparationConstraint *separation140664475523296 = new SeparationConstraint(vpsc::XDIM, 32, 120, 62, true); + ccs.push_back(separation140664475523296); + + AlignmentConstraint *alignment140664475523440 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475523440->addShape(33, 0); + alignment140664475523440->addShape(121, 0); + ccs.push_back(alignment140664475523440); + + SeparationConstraint *separation140664475523664 = new SeparationConstraint(vpsc::XDIM, 33, 121, 62, true); + ccs.push_back(separation140664475523664); + + AlignmentConstraint *alignment140664475523808 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475523808->addShape(34, 0); + alignment140664475523808->addShape(122, 0); + ccs.push_back(alignment140664475523808); + + SeparationConstraint *separation140664475524032 = new SeparationConstraint(vpsc::YDIM, 34, 122, -50, true); + ccs.push_back(separation140664475524032); + + AlignmentConstraint *alignment140664475524176 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475524176->addShape(35, 0); + alignment140664475524176->addShape(123, 0); + ccs.push_back(alignment140664475524176); + + SeparationConstraint *separation140664475524400 = new SeparationConstraint(vpsc::YDIM, 35, 123, -50, true); + ccs.push_back(separation140664475524400); + + AlignmentConstraint *alignment140664475524544 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475524544->addShape(36, 0); + alignment140664475524544->addShape(124, 0); + ccs.push_back(alignment140664475524544); + + SeparationConstraint *separation140664475524768 = new SeparationConstraint(vpsc::YDIM, 36, 124, -50, true); + ccs.push_back(separation140664475524768); + + AlignmentConstraint *alignment140664475524912 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475524912->addShape(37, 0); + alignment140664475524912->addShape(125, 0); + ccs.push_back(alignment140664475524912); + + SeparationConstraint *separation140664475525136 = new SeparationConstraint(vpsc::YDIM, 37, 125, -50, true); + ccs.push_back(separation140664475525136); + + AlignmentConstraint *alignment140664475525280 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475525280->addShape(38, 0); + alignment140664475525280->addShape(126, 0); + ccs.push_back(alignment140664475525280); + + SeparationConstraint *separation140664475525504 = new SeparationConstraint(vpsc::YDIM, 38, 126, -50, true); + ccs.push_back(separation140664475525504); + + AlignmentConstraint *alignment140664475525648 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475525648->addShape(40, 0); + alignment140664475525648->addShape(127, 0); + ccs.push_back(alignment140664475525648); + + SeparationConstraint *separation140664475525872 = new SeparationConstraint(vpsc::YDIM, 40, 127, -50, true); + ccs.push_back(separation140664475525872); + + AlignmentConstraint *alignment140664475526016 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475526016->addShape(41, 0); + alignment140664475526016->addShape(128, 0); + ccs.push_back(alignment140664475526016); + + SeparationConstraint *separation140664475526240 = new SeparationConstraint(vpsc::XDIM, 41, 128, 62, true); + ccs.push_back(separation140664475526240); + + AlignmentConstraint *alignment140664475526384 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475526384->addShape(42, 0); + alignment140664475526384->addShape(129, 0); + ccs.push_back(alignment140664475526384); + + SeparationConstraint *separation140664475526608 = new SeparationConstraint(vpsc::YDIM, 42, 129, -50, true); + ccs.push_back(separation140664475526608); + + AlignmentConstraint *alignment140664475526752 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475526752->addShape(43, 0); + alignment140664475526752->addShape(130, 0); + ccs.push_back(alignment140664475526752); + + SeparationConstraint *separation140664475526976 = new SeparationConstraint(vpsc::YDIM, 43, 130, -50, true); + ccs.push_back(separation140664475526976); + + AlignmentConstraint *alignment140664475527120 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475527120->addShape(44, 0); + alignment140664475527120->addShape(131, 0); + ccs.push_back(alignment140664475527120); + + SeparationConstraint *separation140664475527344 = new SeparationConstraint(vpsc::YDIM, 44, 131, -50, true); + ccs.push_back(separation140664475527344); + + AlignmentConstraint *alignment140664475527488 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475527488->addShape(45, 0); + alignment140664475527488->addShape(132, 0); + ccs.push_back(alignment140664475527488); + + SeparationConstraint *separation140664475527712 = new SeparationConstraint(vpsc::YDIM, 45, 132, -50, true); + ccs.push_back(separation140664475527712); + + AlignmentConstraint *alignment140664475527856 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475527856->addShape(46, 0); + alignment140664475527856->addShape(133, 0); + ccs.push_back(alignment140664475527856); + + SeparationConstraint *separation140664475528080 = new SeparationConstraint(vpsc::YDIM, 46, 133, -50, true); + ccs.push_back(separation140664475528080); + + AlignmentConstraint *alignment140664475528224 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475528224->addShape(47, 0); + alignment140664475528224->addShape(134, 0); + ccs.push_back(alignment140664475528224); + + SeparationConstraint *separation140664475528448 = new SeparationConstraint(vpsc::YDIM, 47, 134, -50, true); + ccs.push_back(separation140664475528448); + + AlignmentConstraint *alignment140664475528592 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475528592->addShape(77, 0); + alignment140664475528592->addShape(135, 0); + ccs.push_back(alignment140664475528592); + + SeparationConstraint *separation140664475528816 = new SeparationConstraint(vpsc::YDIM, 77, 135, -50, true); + ccs.push_back(separation140664475528816); + + AlignmentConstraint *alignment140664475528960 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475528960->addShape(78, 0); + alignment140664475528960->addShape(136, 0); + ccs.push_back(alignment140664475528960); + + SeparationConstraint *separation140664475529184 = new SeparationConstraint(vpsc::YDIM, 78, 136, -50, true); + ccs.push_back(separation140664475529184); + + AlignmentConstraint *alignment140664475529328 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475529328->addShape(79, 0); + alignment140664475529328->addShape(137, 0); + ccs.push_back(alignment140664475529328); + + SeparationConstraint *separation140664475529552 = new SeparationConstraint(vpsc::YDIM, 79, 137, -50, true); + ccs.push_back(separation140664475529552); + + AlignmentConstraint *alignment140664475529696 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475529696->addShape(81, 0); + alignment140664475529696->addShape(138, 0); + ccs.push_back(alignment140664475529696); + + SeparationConstraint *separation140664475529920 = new SeparationConstraint(vpsc::XDIM, 81, 138, 62, true); + ccs.push_back(separation140664475529920); + + AlignmentConstraint *alignment140664475530064 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475530064->addShape(82, 0); + alignment140664475530064->addShape(139, 0); + ccs.push_back(alignment140664475530064); + + SeparationConstraint *separation140664475530288 = new SeparationConstraint(vpsc::YDIM, 82, 139, -50, true); + ccs.push_back(separation140664475530288); + + AlignmentConstraint *alignment140664475530432 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475530432->addShape(83, 0); + alignment140664475530432->addShape(140, 0); + ccs.push_back(alignment140664475530432); + + SeparationConstraint *separation140664475530656 = new SeparationConstraint(vpsc::YDIM, 83, 140, -50, true); + ccs.push_back(separation140664475530656); + + AlignmentConstraint *alignment140664475530800 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475530800->addShape(84, 0); + alignment140664475530800->addShape(141, 0); + ccs.push_back(alignment140664475530800); + + SeparationConstraint *separation140664475531024 = new SeparationConstraint(vpsc::YDIM, 84, 141, -50, true); + ccs.push_back(separation140664475531024); + + AlignmentConstraint *alignment140664475531168 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475531168->addShape(85, 0); + alignment140664475531168->addShape(142, 0); + ccs.push_back(alignment140664475531168); + + SeparationConstraint *separation140664475531392 = new SeparationConstraint(vpsc::XDIM, 85, 142, 62, true); + ccs.push_back(separation140664475531392); + + AlignmentConstraint *alignment140664475531536 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475531536->addShape(87, 0); + alignment140664475531536->addShape(143, 0); + ccs.push_back(alignment140664475531536); + + SeparationConstraint *separation140664475531760 = new SeparationConstraint(vpsc::YDIM, 87, 143, -50, true); + ccs.push_back(separation140664475531760); + + AlignmentConstraint *alignment140664475531904 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475531904->addShape(88, 0); + alignment140664475531904->addShape(144, 0); + ccs.push_back(alignment140664475531904); + + SeparationConstraint *separation140664475532128 = new SeparationConstraint(vpsc::YDIM, 88, 144, -50, true); + ccs.push_back(separation140664475532128); + + AlignmentConstraint *alignment140664475532272 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475532272->addShape(90, 0); + alignment140664475532272->addShape(145, 0); + ccs.push_back(alignment140664475532272); + + SeparationConstraint *separation140664475532496 = new SeparationConstraint(vpsc::YDIM, 90, 145, -50, true); + ccs.push_back(separation140664475532496); + + AlignmentConstraint *alignment140664475532640 = new AlignmentConstraint(vpsc::YDIM, 0); + alignment140664475532640->addShape(91, 0); + alignment140664475532640->addShape(146, 0); + ccs.push_back(alignment140664475532640); + + SeparationConstraint *separation140664475532864 = new SeparationConstraint(vpsc::XDIM, 91, 146, 62, true); + ccs.push_back(separation140664475532864); + + AlignmentConstraint *alignment140664475533008 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475533008->addShape(92, 0); + alignment140664475533008->addShape(147, 0); + ccs.push_back(alignment140664475533008); + + SeparationConstraint *separation140664475533232 = new SeparationConstraint(vpsc::YDIM, 92, 147, -50, true); + ccs.push_back(separation140664475533232); + + AlignmentConstraint *alignment140664475533376 = new AlignmentConstraint(vpsc::XDIM, 0); + alignment140664475533376->addShape(93, 0); + alignment140664475533376->addShape(148, 0); + ccs.push_back(alignment140664475533376); + + SeparationConstraint *separation140664475533600 = new SeparationConstraint(vpsc::YDIM, 93, 148, -50, true); + ccs.push_back(separation140664475533600); + + RootCluster *cluster140664475533920 = new RootCluster(); + + RectangularCluster *cluster140664475534416 = new RectangularCluster(5); + cluster140664475534416->addChildNode(149); + cluster140664475534416->addChildNode(150); + cluster140664475534416->addChildNode(151); + cluster140664475534416->addChildNode(152); + cluster140664475533920->addChildCluster(cluster140664475534416); + + RectangularCluster *cluster140664475535040 = new RectangularCluster(6); + cluster140664475535040->addChildNode(153); + cluster140664475533920->addChildCluster(cluster140664475535040); + + RectangularCluster *cluster140664475535648 = new RectangularCluster(15); + cluster140664475533920->addChildCluster(cluster140664475535648); + + RectangularCluster *cluster140664475535952 = new RectangularCluster(17); + cluster140664475535952->addChildNode(154); + cluster140664475535952->addChildNode(155); + cluster140664475533920->addChildCluster(cluster140664475535952); + + RectangularCluster *cluster140664475536320 = new RectangularCluster(21); + cluster140664475536320->addChildNode(156); + cluster140664475533920->addChildCluster(cluster140664475536320); + + RectangularCluster *cluster140664475536720 = new RectangularCluster(39); + cluster140664475533920->addChildCluster(cluster140664475536720); + + RectangularCluster *cluster140664475537056 = new RectangularCluster(80); + cluster140664475537056->addChildNode(157); + cluster140664475533920->addChildCluster(cluster140664475537056); + + ConstrainedFDLayout alg(rs, es, defaultEdgeLength); + alg.setAvoidNodeOverlaps(true); + alg.setClusterHierarchy(cluster140664475533920); + alg.setConstraints(ccs); + alg.makeFeasible(); + + alg.outputInstanceToSVG("test-rectclustershapecontainment"); + //alg.run(); + alg.freeAssociatedObjects(); + + return 0; +}; diff --git a/src/3rdparty/adaptagrams/libcola/tests/resize.cpp b/src/3rdparty/adaptagrams/libcola/tests/resize.cpp new file mode 100644 index 0000000..97c2e9d --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/resize.cpp @@ -0,0 +1,132 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file nodedragging.cpp + * + * tests interaction with layout and solver. We have a number of disconnected + * shapes. One shape is "dragged" through the others. Overlaps should be + * avoided. + */ +/* +* Authors: +* Tim Dwyer <tgdwyer@gmail.com> +*/ +#include <iostream> +#include <iomanip> +#include <fstream> + +#include <vector> +#include <valarray> +#include <algorithm> +#include <float.h> +#include <libcola/cola.h> +#include <libtopology/topology_graph.h> +#include <libproject/project.h> +#include "graphlayouttest.h" +using namespace std; +using namespace cola; + +string outFName="resize"; + +topology::Node* addNode( + topology::Nodes& vs, vpsc::Rectangle* r) { + topology::Node *v = new topology::Node(vs.size(), r); + vs.push_back(v); + return v; +} +void addToPath(topology::EdgePoints& ps, topology::Node *v, topology::EdgePoint::RectIntersect i) { + ps.push_back(new topology::EdgePoint(v,i)); +} +struct Test : TestConvergence { + Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es) : TestConvergence(d,i), vs(vs), es(es), iter(1) {} + bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) { + bool converged = TestConvergence::operator()(new_stress,X,Y); + if(converged) { + cout << "stress="<<new_stress<<" iteration="<<iter<<endl; + stringstream ss; + ss<<outFName<<"-"<< setfill('0') << setw(3) << iter++ << ".svg"; + writeFile(vs,es,ss.str()); + } + return converged; + } + double lastStress; + topology::Nodes& vs; + topology::Edges& es; + int iter; +}; + +void resize() { +//printf( +//"tests resizing of a shape. We have a number of disconnected" +//"shapes. One shape is 'enlarged'. Overlaps should be" +//"avoided." +//"\n"); + const unsigned V = 9; + Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 0) }; + const std::size_t E = sizeof(edge_array) / sizeof(Edge); + vector<Edge> es(edge_array,edge_array+E); + vector<vpsc::Rectangle*> rs; + const double w=54, h=34; + const double + x[]={406, 444, 474, 406, 441, 375, 408, 373, 339}, + y[]={279, 224, 179, 92, 135, 135, 179, 226, 179}; + const unsigned resizeID=6; + for(unsigned i=0;i<V;++i) { + rs.push_back(new vpsc::Rectangle(x[i],x[i]+w,y[i],y[i]+h)); + } + double idealLength=60; + // set up topology graph + topology::Nodes vs; + for(vector<Rectangle*>::iterator i = rs.begin(); i!=rs.end();++i) { + addNode(vs,*i); + } + topology::Edges tes; + writeFile(vs,tes,outFName+"-000.svg"); + + Resizes resize; + vpsc::Rectangle* r=rs[resizeID]; + resize.push_back(Resize(resizeID,r->getCentreX()-30, r->getCentreY()-30, + r->width()+60,r->height()+60)); + PreIteration preIteration(resize); + Test test(0.00001,100,vs,tes); + ConstrainedFDLayout alg(rs,es,idealLength,nullptr,test,&preIteration); + alg.setTopology(&vs,&tes); + + alg.run(true,true); + + double finalStress=alg.computeStress(); + printf("finalStress=%f\n",finalStress); + + //assert(finalStress<1e-5); + for_each(rs.begin(),rs.end(),delete_object()); + for_each(tes.begin(),tes.end(),delete_object()); + for_each(vs.begin(),vs.end(),delete_object()); +} +int main() { + resize(); + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 : + diff --git a/src/3rdparty/adaptagrams/libcola/tests/runtest.sh b/src/3rdparty/adaptagrams/libcola/tests/runtest.sh new file mode 100755 index 0000000..2ee1526 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/runtest.sh @@ -0,0 +1,8 @@ +#!/bin/bash +r=0 +while [ $r == 0 ] +do + ./beautify + r=$? + echo result=$r +done diff --git a/src/3rdparty/adaptagrams/libcola/tests/scale_free.cpp b/src/3rdparty/adaptagrams/libcola/tests/scale_free.cpp new file mode 100644 index 0000000..d9c2934 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/scale_free.cpp @@ -0,0 +1,135 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +// generates a random graph with a power-law distribution of node degrees +// the algorithm is pretty much the Barabasi-Albert model but with an extra step +// so that I can guarantee the number of nodes in the graph. +// We begin with an initial chain of m nodes. +// Then, we add new nodes, connecting them to existing nodes v with probability +// degree(v)/(sum all degrees) +// We perform an extra step, looking for disconnected nodes, connecting them +// to other nodes again with probability dependent on degree +#include<iostream> +#include<vector> +#include <cmath> +#include <time.h> +#include <valarray> + +#include "graphlayouttest.h" + +void scale_free(const unsigned n = 50) { + const unsigned m = 3; // begin with a chain of m nodes + const double g=0.08; // edge density, every time we add a node we add 1+g*rand(0-1) edges + // connecting them to existing nodes with probability based on degree + unsigned d[n]; + double defaultEdgeLength=100; + vector<Edge> es; + CompoundConstraints cx,cy; + for(unsigned i=0;i<n;i++) { + d[i]=0; + } + unsigned sumdegree=0; + for(unsigned i=1;i<m;i++) { + es.push_back(make_pair(i-1,i)); + d[i]++;d[i-1]++; + sumdegree+=2; + } + srand(3); + for(unsigned i=2;i<n;i++) { + for(unsigned j=0;j<i;j++) { + double p=(double)d[j]/(double)sumdegree; + double r=(double)rand()/(double)RAND_MAX; + if(r*p>g) { + es.push_back(make_pair(j,i)); + d[j]++;d[i]++; + sumdegree+=2; + } + } + } + for(unsigned i=0;i<n;i++) { + if(d[i]==0) { + double maxP=0; + unsigned end=0; + for(unsigned j=0;j<n;j++) { + if(j==i) continue; + double p=(double)d[j]/(double)sumdegree; + double r=(double)rand()/(double)RAND_MAX; + if(r*p>maxP) { + maxP=r*p; + end=j; + } + } + if(end>i) { + es.push_back(make_pair(i,end)); + } else { + es.push_back(make_pair(end,i)); + } + d[end]++;d[i]++; + sumdegree+=2; + } + } + valarray<double> eweights(es.size()); + sort(d,d+n); + unsigned degree=0,ctr=0; + printf("degree distribution:\n"); + for(unsigned i=0;i<n;i++) { + if(degree!=d[i]) { + if(degree!=0) printf("%d,%d\n",degree,ctr); + degree=d[i]; + ctr=0; + } + ctr++; + } + printf("%d,%d\n",degree,ctr); + for(unsigned i=0;i<es.size();i++) { + unsigned a=es[i].first, b=es[i].second; + eweights[i]=1; + cy.push_back(new SeparationConstraint(a,b,defaultEdgeLength/3)); + } + + cout << "|V|="<<n<<endl; + double width=1000; + double height=1000; + vector<pair<double,double> > startpos(n); + for(unsigned i=0;i<n;i++) { + double x=getRand(width), y=getRand(height); + startpos[i]=make_pair(x,y); + } + const char *f="scalefree"; + //run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,f,"cg"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,f,"ip"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,f,"ugp"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,f,"sgp"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,f,"cip"); + //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,f,"cugp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,f,"csgp"); +} +int main() { + for(unsigned i=1;i<2;i++) { + scale_free(i*50); + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/shortest_paths.cpp b/src/3rdparty/adaptagrams/libcola/tests/shortest_paths.cpp new file mode 100644 index 0000000..617f136 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/shortest_paths.cpp @@ -0,0 +1,140 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <fstream> +#include <iostream> +#include <iomanip> +//#define TEST_AGAINST_BOOST +#ifdef TEST_AGAINST_BOOST +#include <boost/config.hpp> +#include <boost/property_map.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/graphviz.hpp> +#include <boost/graph/johnson_all_pairs_shortest.hpp> +using namespace boost; +#endif // TEST_AGAINST_BOOST +#include <libcola/shortest_paths.h> +#include <cmath> +#include <time.h> +#include <assert.h> + +using namespace std; +// creates a (not necessarily connected random graph) with n nodes. +vector<shortest_paths::Edge> random_graph(unsigned n) { + vector<shortest_paths::Edge> edges; + for(unsigned i=0;i<n;i++) { + for(unsigned j=i+1;j<n;j++) { + double r=(double)rand()/(double)RAND_MAX; + if(r < 0.1) { + edges.push_back(make_pair(i,j)); + } + } + } + + return edges; +} +clock_t lastTime; +static void resetClock() { + lastTime=clock(); +} +static double getRunTime() { + clock_t time = clock()-lastTime; + return (double)time/(double)CLOCKS_PER_SEC; +} + +int +main(void) +{ + bool dump=false; + srand(time(0)); +#ifdef TEST_AGAINST_BOOST + typedef adjacency_list<vecS, vecS, undirectedS, no_property, + property< edge_weight_t, double, property< edge_weight2_t, double > > > Graph; + Graph g; +#endif + unsigned V = 100; + vector<shortest_paths::Edge> es = random_graph(V); + unsigned E=es.size(); + cout << " Test graph |V|="<<V<<",|E|="<<E<<endl; + valarray<double> weights(E); + for(unsigned i=0;i<E;i++) { + weights[i]=round((static_cast<double>(rand())/static_cast<double>(RAND_MAX))*10); +#ifdef TEST_AGAINST_BOOST + add_edge(es[i].first,es[i].second,weights[i],g); +#endif + } + +#ifdef TEST_AGAINST_BOOST + vector < double >d(V, (numeric_limits < double >::max)()); + typedef vector<double> weight_vec; + vector<weight_vec> D(V,weight_vec(V)); + cout<<"Running boost::johnson_all_pairs_shortest_paths..."<<endl; + resetClock(); + johnson_all_pairs_shortest_paths(g, D, distance_map(&d[0])); + cout<<" ...done, time="<<getRunTime()<<endl; +#endif + double** D1=new double*[V]; + for(unsigned i=0;i<V;i++) { + D1[i]=new double[V]; + } + cout<<"Running shortest_paths::johnsons..."<<endl; + resetClock(); + shortest_paths::johnsons(V,D1,es,weights); + cout<<" ...done, time="<<getRunTime()<<endl; + double** D2=new double*[V]; + for(unsigned i=0;i<V;i++) { + D2[i]=new double[V]; + } + cout<<"Running shortest_paths::floyd_warshall..."<<endl; + resetClock(); + shortest_paths::floyd_warshall(V,D2,es,weights); + cout<<" ...done, time="<<getRunTime()<<endl; + + for (unsigned int i = 0; i < V; ++i) { + if(dump) cout << i << " -> "; + for (unsigned int j = 0; j < V; ++j) { + if(dump) cout << setw(5) << D1[i][j]; + assert(D1[i][j]==D2[i][j]); +#ifdef TEST_AGAINST_BOOST + assert(D[i][j]==D2[i][j]); +#endif + } + if(dump) cout << endl; + } +#ifdef TEST_AGAINST_BOOST + if(dump) { + ofstream fout("figs/johnson-eg.dot"); + fout << "graph A {\n" << "node[shape=\"circle\"]\n"; + + graph_traits < Graph >::edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + fout << source(*ei, g) << " -- " << target(*ei, g) + << "[label=" << get(edge_weight, g)[*ei] << "]\n"; + + fout << "}\n"; + } +#endif + return 0; +} diff --git a/src/3rdparty/adaptagrams/libcola/tests/small_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/small_graph.cpp new file mode 100644 index 0000000..53103c9 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/small_graph.cpp @@ -0,0 +1,111 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +// Loads a graph from a text file, generates constraints for each edge requiring them +// to point downwards, and proceeds to produce a layout using libcola. +// The input file format is 2 numeric node labels per line separated by a space, +// each pair representing a directed edge. Node labels are simply used as array +// offsets so they should start from 0. +// The graph should be connected. +// Default input file is the matrix market 1138_bus graph. +// Running times: +// no constraints - steepest descent solver: 149 seconds +// no constraints - conjugate gradient solver: 21.7 seconds +// dir-edge constraints - conj grad. solver: 155.69 seconds +#include<iostream> +#include<iomanip> +#include<fstream> +#include<vector> +#include<valarray> +#include<libcola/output_svg.h> +#include<graphlayouttest.h> + +using namespace std; +using namespace cola; + +struct CheckProgress : TestConvergence { + CheckProgress(const double d,const unsigned i) : TestConvergence(d,i) {} + bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) { + cout << "stress="<<new_stress<<endl; + return TestConvergence::operator()(new_stress,X,Y); + } +}; +int main() { + const char *fname="data/wheel.txt"; //"data/dg_850.txt"; + ifstream f(fname); + if(!f.is_open()) { + cout << "Error opening file: " << fname << endl; + exit(1); + } + string startlabel, endlabel; + unsigned V = 0; + double defaultEdgeLength=40; + vector<Edge> es; + CompoundConstraints cy; + //CompoundConstraints cx; + while(!getline(f,startlabel,' ').eof()) { + getline(f,endlabel); + unsigned start = atoi(startlabel.c_str()), + end = atoi(endlabel.c_str()); + es.push_back(make_pair(start,end)); + //cx.push_back( + //new SeparationConstraint(start,end,defaultEdgeLength/3)); + cy.push_back( + new SeparationConstraint(start,end,defaultEdgeLength/3)); + V=max(V,max(start,end)); + } + V++; + cout << "V="<<V<<endl; + double width=1000; + double height=1000; + vector<vpsc::Rectangle*> rs; + //srand(time(nullptr)); + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+1,y,y+1)); + } + CheckProgress test(0.001,100); + clock_t starttime=clock(); + ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test); + bool constrained=false; + if(!constrained) { + cout << "Unconstrained layout" << endl; + alg.setConstrainedLayout(true); + alg.run(); + } else { + cout << "Constrained layout" << endl; + //alg.setXConstraints(&cx); + alg.setYConstraints(&cy); + alg.run(); + } + double t=double(clock()-starttime)/double(CLOCKS_PER_SEC); + cout<<"Time="<<t<<endl; + output_svg(rs,es,nullptr,"small_graph.svg",true); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/sparse_matrix.cpp b/src/3rdparty/adaptagrams/libcola/tests/sparse_matrix.cpp new file mode 100644 index 0000000..099fcf3 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/sparse_matrix.cpp @@ -0,0 +1,88 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <map> +#include <valarray> +#include <libcola/sparse_matrix.h> +#include <boost/numeric/ublas/matrix_sparse.hpp> +#include <boost/numeric/ublas/vector.hpp> +#include <boost/numeric/ublas/io.hpp> +#include <time.h> +#include <cmath> + +using namespace boost::numeric::ublas; +int sparse_test(const unsigned n, cola::SparseMatrix::SparseMap& cm, mapped_matrix<double>& bm) { + printf("Sparse test..."); + srand(time(0)); + for (unsigned i = 0; i < n; ++ i) { + for (unsigned j = 0; j < n; ++ j) { + double r=(double)rand()/(double)RAND_MAX; + double s=(double)rand()/(double)RAND_MAX; + if(r < 0.2) { + cm[std::make_pair(i,j)] = s; + bm (i, j) = s; + } + } + } +} +int dense_test(const unsigned n, cola::SparseMatrix::SparseMap& cm, mapped_matrix<double>& bm) { + printf("Dense test..."); + for (unsigned i = 0; i < n; ++ i) { + for (unsigned j = 0; j < n; ++ j) { + bm (i, j) = n * i + j; + cm[std::make_pair(i,j)]=bm(i,j); + } + } +} + +void test(int (*generate)(const unsigned, cola::SparseMatrix::SparseMap&, mapped_matrix<double>&)) { + using std::valarray; + const unsigned n = 20; + mapped_matrix<double> bm (n, n, n * n); + cola::SparseMatrix::SparseMap cm; + generate(n,cm,bm); + vector<double> bv (n); + valarray<double> cv(n); + for (unsigned i = 0; i < n; ++ i) { + bv(i) = i; + cv[i] = i; + } + vector<double> br(n); + valarray<double> cr(n); + cola::SparseMatrix a(cm,n); + br=prod(bm,bv); + a.rightMultiply(cv,cr); + for (unsigned i = 0; i < n; ++ i) { + assert(fabs(cr[i]-br(i))<0.000001); + } + printf(" passed!\n"); +} +int main() { + test(&dense_test); + test(&sparse_test); + return 0; +} + +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/test_cg.cpp b/src/3rdparty/adaptagrams/libcola/tests/test_cg.cpp new file mode 100644 index 0000000..13e7d02 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/test_cg.cpp @@ -0,0 +1,164 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <stdio.h> +#include <cassert> +#include <libcola/conjugate_gradient.h> +#include <gsl/gsl_linalg.h> + +using std::valarray; + +static valarray<double> +outer_prod(valarray<double> x, valarray<double> y) { + valarray<double> result(x.size()*y.size()); + for(int j = 0; j < x.size(); j++) { + for(int i = 0; i < y.size(); i++) { + result[j*y.size() + i] = x[j]*y[i]; + } + } + return result; +} + +static double +uniform() { + return double(rand())/ RAND_MAX; +} + +static void +matrix_times_vector(valarray<double> const &matrix, /* m * n */ + valarray<double> const &vec, /* n */ + valarray<double> &result) /* m */ +{ + unsigned n = vec.size(); + unsigned m = result.size(); + assert(m*n == matrix.size()); + const double* mp = &matrix[0]; + for (unsigned i = 0; i < m; i++) { + double res = 0; + for (unsigned j = 0; j < n; j++) + res += *mp++ * vec[j]; + result[i] = res; + } +} + +static double +Linfty(valarray<double> const &vec) { + return std::max(vec.max(), -vec.min()); +} + +int +main (void) +{ + double tolerance = 1e-6; + for(int iters = 0; iters < 100; iters++) { + const unsigned N = unsigned(uniform()*40) + 1; + double A_data[N*N]; + printf("%ux%u matrix\n", N,N); + for(int r = 0; r < N; r++) { + for(int c = 0; c <= r; c++) { + A_data[r*N + c] = A_data[c*N + r] = fabs(uniform()); + } + } + + double * A_c[N]; + for(int i = 0; i < N; i++) + A_c[i] = &A_data[N*i]; + + double b_data[N]; + for(int i = 0; i < N; i++) + b_data[i] = uniform()*3; + std::valarray<double> b(b_data, N), xx(0.0, N); + std::valarray<double> A(A_data, N*N); + + conjugate_gradient(A, xx, b, N, tolerance, 2*N); + + gsl_matrix_view m + = gsl_matrix_view_array (A_data, N, N); + gsl_vector_view bgsl + = gsl_vector_view_array (b_data, N); + + gsl_vector *xgsl = gsl_vector_alloc (N); + + int s; + + gsl_permutation * p = gsl_permutation_alloc (N); + + gsl_linalg_LU_decomp (&m.matrix, p, &s); + + gsl_linalg_LU_solve (&m.matrix, p, &bgsl.vector, xgsl); + + std::valarray<double> gsl_xx(0.0, N); + for(unsigned i = 0; i < xx.size(); i++) { + gsl_xx[i] = gsl_vector_get(xgsl, i); + } + + double err = Linfty(xx - gsl_xx); + printf ("|xx-nxgsl|_infty = %g\n", err); + if(err > tolerance) { +#if 0 //dubious value + for(int r = 0; r < N; r++) { + for(int c = 0; c < N; c++) { + printf("%g ", A_data[r*N + c]); + } + printf("\n"); + } +#endif + printf("\nx njh-cg = \n"); + for(unsigned i = 0; i < xx.size(); i++) + printf("%g ", xx[i]); + printf("\nxgsl = "); + for(unsigned i = 0; i < xx.size(); i++) + printf("%g ", gsl_xx[i]); + printf("\n"); + valarray<double> result(0.0,N); + matrix_times_vector(A, xx, result); + result -= b; + printf("\nA xx -b = "); + for(unsigned i = 0; i < xx.size(); i++) + printf("%g ", result[i]); + printf("\n"); + matrix_times_vector(A, gsl_xx, result); + result -= b; + printf("\nA gsl_xx -b = "); + for(unsigned i = 0; i < xx.size(); i++) + printf("%g ", result[i]); + printf("\n"); + + printf("FAILED!!!!!!!!!!!!!!!!!!!!!!!!\n"); + exit(1); + } + } + return 0; +} +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 diff --git a/src/3rdparty/adaptagrams/libcola/tests/topology.cpp b/src/3rdparty/adaptagrams/libcola/tests/topology.cpp new file mode 100644 index 0000000..4c94ef7 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/topology.cpp @@ -0,0 +1,177 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file topology.cpp + * + * tests topology preserving layout. graph is a triangle. + * We have a fourth disconnected node starting inside the triangle. + * We give the disconnected node a desired position outside the triangle + * and begin layout. Layout should converge to near zero stress as all + * edges should be able to reach their desired lengths, and disconnected + * node should still be inside the triangle at the end. + * + * + * Authors: + * Tim Dwyer <tgdwyer@gmail.com> + */ +#include <iostream> +#include <iomanip> +#include <fstream> + +#include <vector> +#include <valarray> +#include <algorithm> +#include <float.h> +#include <libcola/cola.h> +#include <libtopology/topology_graph.h> +#include "graphlayouttest.h" +using namespace std; +using namespace cola; + +topology::Node* addNode( + topology::Nodes& vs, vpsc::Rectangle* r) { + topology::Node *v = new topology::Node(vs.size(), r); + vs.push_back(v); + return v; +} +void addToPath(topology::EdgePoints& ps, topology::Node *v, topology::EdgePoint::RectIntersect i) { + ps.push_back(new topology::EdgePoint(v,i)); +} +struct SetDesiredPos : public PreIteration { + SetDesiredPos(Locks& locks) : PreIteration(locks) {} + bool operator()() { + return true; + } +}; +void writeFile(const topology::Nodes& vs, const topology::Edges& es, const char *outputFileName) { + const unsigned n=vs.size(); + vector<cola::Edge> cedges; + + for(unsigned i=0;i<es.size();i++) { + cedges.push_back(make_pair(1,2)); + } + + vector<straightener::Route*> routes; + for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) { + routes.push_back((*e)->getRoute()); + } + + vector<string> labels(n); + for(unsigned i=0;i<n;++i) { + stringstream ss; + ss << i; + labels[i]=ss.str(); + } + + vector<vpsc::Rectangle*> rs; + for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) { + rs.push_back((*i)->rect); + } + OutputFile of(rs,cedges,nullptr,outputFileName,true,false); + of.setLabels(labels); + of.routes=&routes; + of.generate(); + + for_each(routes.begin(),routes.end(),delete_object()); +} +struct Test : TestConvergence { + Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es) : TestConvergence(d,i), vs(vs), es(es) {} + bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) { + cout << "stress="<<new_stress<<" iteration="<<iterations<<endl; + stringstream ss; + ss << "topology-" << setfill('0') << setw(3) << ++iterations << ".svg"; + writeFile(vs,es,ss.str().c_str()); + if(iterations<100) { + return false; + } + return true; + return TestConvergence::operator()(new_stress,X,Y); + } + double lastStress; + topology::Nodes& vs; + topology::Edges& es; +}; +void randomMove(int i) { + printf("We have a triangle of three connected nodes and a fourth disconnected node. We set the fourth node's desired position at a point some random direction outside the triangle.\n"); + printf("Using srand=%d\n",i); + srand(i); + const unsigned V = 4; + Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 0) }; + const std::size_t E = sizeof(edge_array) / sizeof(Edge); + vector<Edge> es(edge_array,edge_array+E); + vector<vpsc::Rectangle*> rs; + double x[]={200,250,300,250},y[]={200,250,200,225},size=10; + for(unsigned i=0;i<V;++i) { + rs.push_back(new vpsc::Rectangle(x[i],x[i]+size,y[i],y[i]+size)); + } + double idealLength=60; + // set up topology graph + topology::Nodes vs; + for(vector<Rectangle*>::iterator i = rs.begin(); i!=rs.end();++i) { + addNode(vs,*i); + } + topology::Edges tes; + unsigned eID=0; + for(vector<Edge>::iterator e=es.begin();e!=es.end();++e, ++eID) { + topology::EdgePoints ps; + addToPath(ps,vs[e->first],topology::EdgePoint::CENTRE); + addToPath(ps,vs[e->second],topology::EdgePoint::CENTRE); + tes.push_back(new topology::Edge(eID, idealLength, ps)); + } + writeFile(vs,tes,"topology-000.svg"); + Locks locks; + // we move the 4th node somewhere outside the triangle. The triangle should be + // dragged along! + const double PI = 2.0*acos(0.0); + double angle = getRand(2.0*PI); + double dx=150*cos(angle), dy=150*sin(angle); + + double lx=rs[3]->getCentreX()+dx, + ly=rs[3]->getCentreY()+dy; + //double lx=353.886210, ly=342.789705; + locks.push_back(Lock(3,lx,ly)); + printf(" Lock: %f,%f\n",lx,ly); + SetDesiredPos preIteration(locks); + Test test(0.00001,100,vs,tes); + ConstrainedFDLayout alg(rs,es,idealLength,nullptr,test,&preIteration); + + alg.setTopology(&vs,&tes); + alg.run(true,true); + double finalStress=alg.computeStress(); + printf("finalStress=%f\n",finalStress); + + //assert(finalStress<1e-5); + for_each(rs.begin(),rs.end(),delete_object()); + for_each(tes.begin(),tes.end(),delete_object()); + for_each(vs.begin(),vs.end(),delete_object()); +} +int main() { + unsigned i=0; + for(;i<1;i++) { + randomMove(i); + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/trees.cpp b/src/3rdparty/adaptagrams/libcola/tests/trees.cpp new file mode 100644 index 0000000..72fb296 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/trees.cpp @@ -0,0 +1,103 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include<iostream> +#include<vector> +#include <cmath> +#include <time.h> +#include <valarray> + +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; + +void makeEdge(unsigned u, unsigned v, + vector<Edge> &edges, CompoundConstraints &cy) { + edges.push_back(make_pair(u,v)); + cy.push_back(new SeparationConstraint(u,v,20)); +} +vector<Edge> random_tree(unsigned depth, unsigned maxbranch, unsigned &V, + CompoundConstraints &cx, CompoundConstraints &cy) { + vector<Edge> edges; + unsigned lstart=0, lend=1; + V=0; + for(unsigned i=0;i<depth;i++) { + for(unsigned j=lstart;j<lend;j++) { + //makeEdge(j,++V,edges,cy); + //makeEdge(j,++V,edges,cy); + for(unsigned k=0;k<maxbranch;k++) { + double r=(double)rand()/(double)RAND_MAX; + if(r < 0.5) { + makeEdge(j,++V,edges,cy); + } + } + } + lstart=lend; + lend=V+1; + } + V++; + DFS::Graph dfs(V,edges); + for(unsigned i=1;i<dfs.order.size();i++) { + cx.push_back( + new SeparationConstraint(dfs.order[i-1],dfs.order[i],0.5)); + } + /* + for(unsigned i=0;i<dfs.leaves.size();i++) { + for(unsigned j=1;j<dfs.leaves[i].size();j++) { + cx.push_back( + new SeparationConstraint(dfs.leaves[i][j-1],dfs.leaves[i][j],10)); + } + } + */ + return edges; +} +int main() { + unsigned V; + CompoundConstraints cx,cy; + //srand(time(nullptr)); + srand(3); + vector<Edge> es = random_tree(7,4,V,cx,cy); + double defaultEdgeLength=40; + + cout << "V="<<V<<endl; + double width=1000; + double height=1000; + vector<pair<double,double> > startpos(V); + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + startpos[i]=make_pair(x,y); + } + const char *testname="trees"; + run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,testname,"cg"); + run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,testname,"ip"); + run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,testname,"sgp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,testname,"ugp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,testname,"cip"); + run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,testname,"csgp"); + run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,testname,"cugp"); + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/unconstrained.cpp b/src/3rdparty/adaptagrams/libcola/tests/unconstrained.cpp new file mode 100644 index 0000000..f6f112b --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/unconstrained.cpp @@ -0,0 +1,71 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/** \file unconstrained.cpp + * + * Unconstrained graph layout test. Simple graph with 4 nodes and 4 edges, + * a triangle with a dangle. Final stress checked. + * + * + * Authors: + * Tim Dwyer <tgdwyer@gmail.com> + */ +#include <iostream> +#include <fstream> + +#include <vector> +#include <valarray> +#include <algorithm> +#include <float.h> +#include "graphlayouttest.h" +using namespace std; + +using namespace cola; +int main() { + + const unsigned V = 4; + Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(1, 3) }; + const std::size_t E = sizeof(edge_array) / sizeof(Edge); + vector<Edge> es(E); + copy(edge_array,edge_array+E,es.begin()); + double width=100; + double height=100; + vector<vpsc::Rectangle*> rs; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5)); + } + CheckProgress test(1e-9,100); + ConstrainedFDLayout alg(rs,es,width/2,nullptr,&test); + alg.run(); + double stress = alg.computeStress(); + assert(stress < 0.0013); + OutputFile output(rs,es,nullptr,"unconstrained.svg"); + output.generate(); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} diff --git a/src/3rdparty/adaptagrams/libcola/tests/unsatisfiable.cpp b/src/3rdparty/adaptagrams/libcola/tests/unsatisfiable.cpp new file mode 100644 index 0000000..4e768f7 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/unsatisfiable.cpp @@ -0,0 +1,85 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file LICENSE; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * +*/ + + +/** \file + * Interface between Inkscape code (SPItem) and graphlayout functions. + * + * Authors: + * Tim Dwyer <tgdwyer@gmail.com> + */ +#include <iostream> + +#include <vector> +#include <algorithm> +#include <float.h> +#include <libcola/cola.h> +#include <libvpsc/exceptions.h> +#include <libvpsc/constraint.h> +#include "graphlayouttest.h" + +using namespace std; +using namespace cola; +int main() { + + const unsigned V = 2; + typedef pair < unsigned, unsigned >Edge; + Edge edge_array[] = { Edge(0, 1) }; + unsigned E = sizeof(edge_array) / sizeof(Edge); + vector<Edge> es(edge_array,edge_array+E); + double width=100; + double height=100; + vector<vpsc::Rectangle*> rs; + for(unsigned i=0;i<V;i++) { + double x=getRand(width), y=getRand(height); + rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5)); + } + ConstrainedFDLayout alg(rs,es,width/2); + CompoundConstraints ccs; + AlignmentConstraint ac(vpsc::YDIM, 1); + ccs.push_back(&ac); + ac.addShape(0,0); + ac.addShape(1,0); + ccs.push_back(new SeparationConstraint(vpsc::YDIM, 0,1,10)); + alg.setConstraints(ccs); + try { + alg.run(); + } catch (vpsc::UnsatisfiableException& e) { + cerr << "Unsatisfiable" << endl; + for(vector<vpsc::Constraint*>::iterator i=e.path.begin(); + i!=e.path.end();i++) { + cout << **i << endl; + } + exit(1); + } + //assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001); + cout<<rs[0]->getCentreX()<<","<<rs[1]->getCentreX()<<endl; + //output_svg(rs,es,"unsatisfiable.svg"); + for(unsigned i=0;i<V;i++) { + delete rs[i]; + } + return 0; +} +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 : diff --git a/src/3rdparty/adaptagrams/libcola/tests/view_cd_output.sh b/src/3rdparty/adaptagrams/libcola/tests/view_cd_output.sh new file mode 100755 index 0000000..cb74ae8 --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/view_cd_output.sh @@ -0,0 +1,43 @@ +#! /bin/bash + +if [ $# -lt 1 ] ; then + echo "Need case letter (eg: A) or ALL for all cases (CLEAN to delete)" + exit +else + CASE=$1 + shift +fi + +cd /home/kierans/libcola3/libcola/tests + +if [ $CASE == 'a' -o $CASE == 'A' ] ; then + inkview cycle_detector_case_a.svg +fi + +if [ $CASE == 'b' -o $CASE == 'B' ] ; then + inkview cycle_detector_case_b.svg +fi + +if [ $CASE == 'c' -o $CASE == 'C' ] ; then + inkview cycle_detector_case_c.svg +fi + +if [ $CASE == 'd' -o $CASE == 'D' ] ; then + inkview cycle_detector_case_d.svg +fi + +if [ $CASE == 'e' -o $CASE == 'E' ] ; then + inkview cycle_detector_case_e.svg +fi + +if [ $CASE == 'f' -o $CASE == 'F' ] ; then + inkview cycle_detector_case_f.svg +fi + +if [ $CASE == 'all' -o $CASE == 'ALL' ] ; then + inkview cycle_detector_case_a.svg cycle_detector_case_b.svg cycle_detector_case_c.svg cycle_detector_case_d.svg cycle_detector_case_e.svg cycle_detector_case_f.svg +fi + +if [ $CASE == 'clean' ] ; then + rm cycle_detector_case* -fv +fi diff --git a/src/3rdparty/adaptagrams/libcola/tests/view_mas_output.sh b/src/3rdparty/adaptagrams/libcola/tests/view_mas_output.sh new file mode 100755 index 0000000..11f5a8a --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/tests/view_mas_output.sh @@ -0,0 +1,43 @@ +#! /bin/bash + +if [ $# -lt 1 ] ; then + echo "Need case letter (eg: A) or ALL for all cases (CLEAN to delete)" + exit +else + CASE=$1 + shift +fi + +cd /home/kierans/libcola3/libcola/tests + +if [ $CASE == 'a' -o $CASE == 'A' ] ; then + inkview mas_case_a.svg +fi + +if [ $CASE == 'b' -o $CASE == 'B' ] ; then + inkview mas_case_b.svg +fi + +if [ $CASE == 'c' -o $CASE == 'C' ] ; then + inkview mas_case_c.svg +fi + +if [ $CASE == 'd' -o $CASE == 'D' ] ; then + inkview mas_case_d.svg +fi + +if [ $CASE == 'e' -o $CASE == 'E' ] ; then + inkview mas_case_e.svg +fi + +if [ $CASE == 'f' -o $CASE == 'F' ] ; then + inkview mas_case_f.svg +fi + +if [ $CASE == 'all' -o $CASE == 'ALL' ] ; then + inkview mas_case_a.svg mas_case_b.svg mas_case_c.svg mas_case_d.svg mas_case_e.svg mas_case_f.svg +fi + +if [ $CASE == 'clean' ] ; then + rm mas_case* -fv +fi diff --git a/src/3rdparty/adaptagrams/libcola/unused.h b/src/3rdparty/adaptagrams/libcola/unused.h new file mode 100644 index 0000000..1e519fe --- /dev/null +++ b/src/3rdparty/adaptagrams/libcola/unused.h @@ -0,0 +1,26 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libcola - A library providing force-directed network layout using the + * stress-majorization method subject to separation constraints. + * + * Copyright (C) 2006-2008 Monash University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * See the file LICENSE.LGPL distributed with the library. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * +*/ + +#ifndef _UNUSED_H +#define _UNUSED_H + +#define COLA_UNUSED(expr) do { (void)(expr); } while (0) + +#endif |