1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
/*
*
* This file is part of Tulip (www.tulip-software.org)
*
* Authors: David Auber and the Tulip development Team
* from LaBRI, University of Bordeaux
*
* Tulip 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 3
* of the License, or (at your option) any later version.
*
* Tulip 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 General Public License for more details.
*
*/
#include <tulip/SizeProperty.h>
#include <tulip/ForEach.h>
#include <tulip/StringCollection.h>
#include "FastOverlapRemoval.h"
#include "generate-constraints.h"
#include "remove_rectangle_overlap.h"
using namespace std;
using namespace tlp;
PLUGIN(FastOverlapRemoval)
static const char* paramHelp[] = {
// layout
HTML_HELP_OPEN()
HTML_HELP_DEF( "type", "String Collection" )
HTML_HELP_DEF("values", "X-Y <i>(Remove overlaps in both X and Y directions)</i><br/>X <i>(Remove overlaps only in X direction)</i><br/>Y <i>(Remove overlaps only in Y direction)</i>")
HTML_HELP_DEF( "default", "X-Y" )
HTML_HELP_BODY()
"Overlaps removal type."
HTML_HELP_CLOSE(),
HTML_HELP_OPEN() \
HTML_HELP_DEF("Type", "LayoutProperty") \
HTML_HELP_DEF("Values", "Any layout property") \
HTML_HELP_DEF("Default", "viewLayout") \
HTML_HELP_BODY() \
"The property used for the input layout of nodes and edges" \
HTML_HELP_CLOSE(),
// node size
HTML_HELP_OPEN() \
HTML_HELP_DEF( "type", "Size" ) \
HTML_HELP_DEF( "values", "An existing size property" ) \
HTML_HELP_DEF( "default", "viewSize" ) \
HTML_HELP_BODY() \
"The property used for node's sizes." \
HTML_HELP_CLOSE(),
//Rotation
HTML_HELP_OPEN() \
HTML_HELP_DEF("Type", "DoubleProperty") \
HTML_HELP_DEF("Values", "Any double property used for rotation of nodes on z-axis") \
HTML_HELP_DEF("Default", "viewRotation") \
HTML_HELP_BODY() \
"The property used as rotation of nodes on z-axis" \
HTML_HELP_CLOSE(),
//Iterations
HTML_HELP_OPEN() \
HTML_HELP_DEF("Type", "int") \
HTML_HELP_DEF("Values", "The number of time the algorithm will be applied with increasing node size.") \
HTML_HELP_DEF("Default", "5") \
HTML_HELP_BODY() \
"The algorithm will be applied N times, each time increasing node size to attain original size at the final iteration. This greatly enhances the layout." \
HTML_HELP_CLOSE(),
HTML_HELP_OPEN() \
HTML_HELP_DEF("Type", "double") \
HTML_HELP_DEF("Values", "floating point number") \
HTML_HELP_DEF("Default", "0.0") \
HTML_HELP_BODY() \
"The minimal x border value that will separate the graph nodes after application of the algorithm" \
HTML_HELP_CLOSE(),
HTML_HELP_OPEN() \
HTML_HELP_DEF("Type", "double") \
HTML_HELP_DEF("Values", "floating point number") \
HTML_HELP_DEF("Default", "0.0") \
HTML_HELP_BODY() \
"The minimal y border value that will separate the graph nodes after application of the algorithm" \
HTML_HELP_CLOSE(),
};
#define OVERLAP_TYPE "X-Y;X;Y"
FastOverlapRemoval::FastOverlapRemoval(const tlp::PluginContext* context) :
tlp::LayoutAlgorithm(context) {
addInParameter<StringCollection> ("overlaps removal type", paramHelp[0], OVERLAP_TYPE);
addInParameter<LayoutProperty>("layout", paramHelp[1], "viewLayout");
addInParameter<SizeProperty>("bounding box", paramHelp[2], "viewSize");
addInParameter<DoubleProperty>("rotation", paramHelp[3], "viewRotation");
addInParameter<int>("number of passes", paramHelp[4], "5");
addInParameter<double>("x border", paramHelp[5], "0.0");
addInParameter<double>("y border", paramHelp[6], "0.0");
}
/**
* The following function transfers the node set into vpsc rectangles
* and runs fast overlap removal. This vpsc code was a port of Dwyer
* used in the InkScape Open Source Software.
*/
bool FastOverlapRemoval::run () {
tlp::StringCollection stringCollection(OVERLAP_TYPE);
stringCollection.setCurrent(0);
LayoutProperty *viewLayout = NULL;
SizeProperty *viewSize = NULL;
DoubleProperty *viewRot = NULL;
double xBorder = 0.;
double yBorder = 0.;
int nbPasses = 5;
if (dataSet != NULL) {
dataSet->get("overlaps removal type", stringCollection);
dataSet->get("layout", viewLayout);
if (!dataSet->get("bounding box", viewSize))
// old name of the parameter
dataSet->get("boundingBox", viewSize);
dataSet->get("rotation", viewRot);
dataSet->get("number of passes", nbPasses);
dataSet->get("x border", xBorder);
dataSet->get("y border", yBorder);
}
if (viewLayout == NULL)
viewLayout = graph->getProperty<LayoutProperty> ("viewLayout");
if (viewSize == NULL)
viewSize = graph->getProperty<SizeProperty> ("viewSize");
if (viewRot == NULL)
viewRot = graph->getProperty<DoubleProperty> ("viewRotation");
// initialize result for edges
result->setAllEdgeValue(viewLayout->getEdgeDefaultValue());
edge e;
forEach(e, viewLayout->getNonDefaultValuatedEdges())
result->setEdgeValue(e, viewLayout->getEdgeValue(e));
SizeProperty size(graph);
for(float passIndex = 1.; passIndex <= nbPasses; ++passIndex) {
node n;
// size initialization
forEach(n, graph->getNodes())
size.setNodeValue(n, viewSize->getNodeValue(n) *
passIndex/(float)nbPasses);
//actually apply fast overlap removal
vector<vpsc::Rectangle *>nodeRectangles (graph->numberOfNodes());
node curNode;
unsigned int nodeCounter = 0;
vector<node> nodeOrder(graph->numberOfNodes());
forEach (curNode, graph->getNodes()) {
const Coord &pos = viewLayout->getNodeValue (curNode);
const Size &sz = size.getNodeValue (curNode);
double curRot = viewRot->getNodeValue (curNode);
Size rotSize = Size (sz.getW()*fabs (cos (curRot*M_PI/180.0)) +
sz.getH()*fabs (sin (curRot*M_PI/180.0)),
sz.getW()*fabs (sin (curRot*M_PI/180.0)) +
sz.getH()*fabs (cos (curRot*M_PI/180.0)), 1.0f);
double maxX = pos.getX() + rotSize.getW()/2.0;
double maxY = pos.getY() + rotSize.getH()/2.0;
double minX = pos.getX() - rotSize.getW()/2.0;
double minY = pos.getY() - rotSize.getH()/2.0;
nodeRectangles[nodeCounter] =
new vpsc::Rectangle (minX, maxX, minY, maxY, xBorder, yBorder);
nodeOrder[nodeCounter] = curNode;
++nodeCounter;
}//end forEach
if (stringCollection.getCurrentString() == "X-Y") {
removeRectangleOverlap(graph->numberOfNodes(),
#if defined(__APPLE__)
&(nodeRectangles[0]),
#else
nodeRectangles.data(),
#endif
xBorder, yBorder);
}
else if (stringCollection.getCurrentString() == "X") {
removeRectangleOverlapX(graph->numberOfNodes(),
#if defined(__APPLE__)
&(nodeRectangles[0]),
#else
nodeRectangles.data(),
#endif
xBorder, yBorder);
}
else {
removeRectangleOverlapY(graph->numberOfNodes(),
#if defined(__APPLE__)
&(nodeRectangles[0]),
#else
nodeRectangles.data(),
#endif
yBorder);
}
for (unsigned int i = 0; i < graph->numberOfNodes(); ++i) {
Coord newPos (nodeRectangles[i]->getCentreX(),
nodeRectangles[i]->getCentreY(), 0.0);
LayoutAlgorithm::result->setNodeValue (nodeOrder[i], newPos);
}//end for
for (unsigned int i = 0; i < graph->numberOfNodes(); ++i)
delete nodeRectangles[i];
}
return true;
}//end run
|