diff options
author | Aleks Kissinger <aleks0@gmail.com> | 2018-01-04 16:00:52 +0100 |
---|---|---|
committer | Aleks Kissinger <aleks0@gmail.com> | 2018-01-04 16:00:52 +0100 |
commit | 738ecbd5fad2b46836bfd6a94aeebf165ae2bbca (patch) | |
tree | df04709807cc9ec8481a3ebc7d80ac25e5b2f457 /src/data/edge.cpp | |
parent | 0421a96749743868554d44585050b1b3d04864d2 (diff) |
relocated source code to the root
Diffstat (limited to 'src/data/edge.cpp')
-rw-r--r-- | src/data/edge.cpp | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/src/data/edge.cpp b/src/data/edge.cpp new file mode 100644 index 0000000..6802b2d --- /dev/null +++ b/src/data/edge.cpp @@ -0,0 +1,306 @@ +#include "edge.h" +#include "tikzit.h" +#include "util.h" + +#include <QDebug> +#include <QPointF> + +Edge::Edge(Node *s, Node *t, QObject *parent) : + QObject(parent), _source(s), _target(t) +{ + _data = new GraphElementData(); + _edgeNode = 0; + _dirty = true; + _basicBendMode = true; + _bend = 0; + _inAngle = 0; + _outAngle = 0; + _weight = 0.4f; + updateControls(); +} + +Edge::~Edge() +{ + delete _data; + delete _edgeNode; +} + +Node *Edge::source() const +{ + return _source; +} + +Node *Edge::target() const +{ + return _target; +} + +bool Edge::isSelfLoop() +{ + return (_source == _target); +} + +bool Edge::isStraight() +{ + return (_basicBendMode && _bend == 0); +} + +GraphElementData *Edge::data() const +{ + return _data; +} + +void Edge::setData(GraphElementData *data) +{ + delete _data; + _data = data; + setAttributesFromData(); +} + +QString Edge::sourceAnchor() const +{ + return _sourceAnchor; +} + +void Edge::setSourceAnchor(const QString &sourceAnchor) +{ + _sourceAnchor = sourceAnchor; +} + +QString Edge::targetAnchor() const +{ + return _targetAnchor; +} + +void Edge::setTargetAnchor(const QString &targetAnchor) +{ + _targetAnchor = targetAnchor; +} + +Node *Edge::edgeNode() const +{ + return _edgeNode; +} + +void Edge::setEdgeNode(Node *edgeNode) +{ + if (_edgeNode != 0) delete _edgeNode; + _edgeNode = edgeNode; +} + +bool Edge::hasEdgeNode() +{ + return _edgeNode != 0; +} + +void Edge::updateControls() { + //if (_dirty) { + QPointF src = _source->point(); + QPointF targ = _target->point(); + + float dx = (targ.x() - src.x()); + float dy = (targ.y() - src.y()); + + float outAngleR = 0.0f; + float inAngleR = 0.0f; + + if (_basicBendMode) { + float angle = std::atan2(dy, dx); + float bnd = (float)_bend * (M_PI / 180.0f); + outAngleR = angle - bnd; + inAngleR = M_PI + angle + bnd; + _outAngle = outAngleR * (180.f / M_PI); + _inAngle = inAngleR * (180.f / M_PI); + } else { + outAngleR = (float)_outAngle * (M_PI / 180.0f); + inAngleR = (float)_inAngle * (M_PI / 180.0f); + } + + // TODO: calculate head and tail properly, not just for circles + if (_source->style()->isNone()) { + _tail = src; + } else { + _tail = QPointF(src.x() + std::cos(outAngleR) * 0.1, + src.y() + std::sin(outAngleR) * 0.1); + } + + if (_target->style()->isNone()) { + _head = targ; + } else { + _head = QPointF(targ.x() + std::cos(inAngleR) * 0.1, + targ.y() + std::sin(inAngleR) * 0.1); + } + + // give a default distance for self-loops + _cpDist = (dx==0.0f && dy==0.0f) ? _weight : std::sqrt(dx*dx + dy*dy) * _weight; + + _cp1 = QPointF(src.x() + (_cpDist * std::cos(outAngleR)), + src.y() + (_cpDist * std::sin(outAngleR))); + + _cp2 = QPointF(targ.x() + (_cpDist * std::cos(inAngleR)), + targ.y() + (_cpDist * std::sin(inAngleR))); + + _mid = bezierInterpolateFull (0.5f, _tail, _cp1, _cp2, _head); +// midTan = [self _findTanFor:mid usingSpanFrom:0.4f to:0.6f]; + +// tailTan = [self _findTanFor:tail usingSpanFrom:0.0f to:0.1f]; +// headTan = [self _findTanFor:head usingSpanFrom:1.0f to:0.9f]; + //_dirty = false; + //} +} + +void Edge::setAttributesFromData() +{ + _basicBendMode = true; + bool ok = true; + + if (_data->atom("bend left")) { + _bend = -30; + } else if (_data->atom("bend right")) { + _bend = 30; + } else if (_data->property("bend left") != 0) { + _bend = -_data->property("bend left").toInt(&ok); + if (!ok) _bend = -30; + } else if (_data->property("bend right") != 0) { + _bend = _data->property("bend right").toInt(&ok); + if (!ok) _bend = 30; + } else { + _bend = 0; + + if (_data->property("in") != 0 && _data->property("out") != 0) { + _basicBendMode = false; + _inAngle = _data->property("in").toInt(&ok); + if (!ok) _inAngle = 0; + _outAngle = _data->property("out").toInt(&ok); + if (!ok) _outAngle = 180; + } + } + + if (_data->property("looseness") != 0) { + _weight = _data->property("looseness").toFloat(&ok) / 2.5f; + if (!ok) _weight = 0.4f; + } else { + _weight = (isSelfLoop()) ? 1.0f : 0.4f; + } + + //qDebug() << "bend: " << _bend << " in: " << _inAngle << " out: " << _outAngle; + _dirty = true; +} + +void Edge::updateData() +{ + _data->unsetAtom("loop"); + _data->unsetProperty("in"); + _data->unsetProperty("out"); + _data->unsetAtom("bend left"); + _data->unsetAtom("bend right"); + _data->unsetProperty("bend left"); + _data->unsetProperty("bend right"); + _data->unsetProperty("looseness"); + + // TODO: style handling? + + if (_basicBendMode && _bend != 0) { + QString bendKey; + int b; + if (_bend < 0) { + bendKey = "bend left"; + b = -_bend; + } else { + bendKey = "bend right"; + b = _bend; + } + + if (b == 30) { + _data->setAtom(bendKey); + } else { + _data->setProperty(bendKey, QString::number(b)); + } + } else { + _data->setProperty("in", QString::number(_inAngle)); + _data->setProperty("out", QString::number(_outAngle)); + } + + if (_source == _target) _data->setAtom("loop"); + if (!isSelfLoop() && !isStraight() && _weight != 0.4f) + _data->setProperty("looseness", QString::number(_weight*2.5f, 'f', 2)); + +} + + +QPointF Edge::head() const +{ + return _head; +} + +QPointF Edge::tail() const +{ + return _tail; +} + +QPointF Edge::cp1() const +{ + return _cp1; +} + +QPointF Edge::cp2() const +{ + return _cp2; +} + +int Edge::bend() const +{ + return _bend; +} + +int Edge::inAngle() const +{ + return _inAngle; +} + +int Edge::outAngle() const +{ + return _outAngle; +} + +float Edge::weight() const +{ + return _weight; +} + +bool Edge::basicBendMode() const +{ + return _basicBendMode; +} + +float Edge::cpDist() const +{ + return _cpDist; +} + +void Edge::setBend(int bend) +{ + _bend = bend; +} + +void Edge::setInAngle(int inAngle) +{ + _inAngle = inAngle; +} + +void Edge::setOutAngle(int outAngle) +{ + _outAngle = outAngle; +} + +void Edge::setWeight(float weight) +{ + _weight = weight; +} + +QPointF Edge::mid() const +{ + return _mid; +} + + |