summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/adaptagrams/libavoid/junction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/adaptagrams/libavoid/junction.cpp')
-rw-r--r--src/3rdparty/adaptagrams/libavoid/junction.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/3rdparty/adaptagrams/libavoid/junction.cpp b/src/3rdparty/adaptagrams/libavoid/junction.cpp
new file mode 100644
index 0000000..f17e37e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/junction.cpp
@@ -0,0 +1,233 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2010-2011 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.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided 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 <cstdlib>
+#include <algorithm>
+
+#include "libavoid/junction.h"
+#include "libavoid/router.h"
+#include "libavoid/connectionpin.h"
+#include "libavoid/debug.h"
+
+
+namespace Avoid {
+
+
+JunctionRef::JunctionRef(Router *router, Point position, const unsigned int id)
+ : Obstacle(router, makeRectangle(router, position), id),
+ m_position(position),
+ m_recommended_position(position),
+ m_position_fixed(false)
+{
+ // For Junctions we use a single non-exclusive pin.
+ ShapeConnectionPin *pin = new Avoid::ShapeConnectionPin(this,
+ Avoid::CONNECTIONPIN_CENTRE, ConnDirAll);
+ pin->setExclusive(false);
+ m_connection_pins.insert(pin);
+
+ m_router->addJunction(this);
+}
+
+JunctionRef::~JunctionRef()
+{
+ if (m_router->m_currently_calling_destructors == false)
+ {
+ err_printf("ERROR: JunctionRef::~JunctionRef() shouldn't be called directly.\n");
+ err_printf(" It is owned by the router. Call Router::deleteJunction() instead.\n");
+ abort();
+ }
+}
+
+
+Rectangle JunctionRef::makeRectangle(Router *router, const Point& position)
+{
+ COLA_ASSERT(router);
+
+ // A suitably small value.
+ double nudgeDist = router->routingParameter(idealNudgingDistance);
+ nudgeDist = std::min(1.0, nudgeDist);
+
+ Point low = position;
+ low.x -= nudgeDist;
+ low.y -= nudgeDist;
+
+ Point high = position;
+ high.x += nudgeDist;
+ high.y += nudgeDist;
+
+ return Rectangle(low, high);
+}
+
+
+void JunctionRef::setPositionFixed(bool fixed)
+{
+ m_position_fixed = fixed;
+ m_router->registerSettingsChange();
+}
+
+
+bool JunctionRef::positionFixed(void) const
+{
+ return m_position_fixed;
+}
+
+
+void JunctionRef::preferOrthogonalDimension(const size_t dim)
+{
+ const double smallPenalty = 1.0;
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *pin = *curr;
+ if (dim == YDIM)
+ {
+ if (pin->directions() & (ConnDirLeft | ConnDirRight))
+ {
+ pin->setConnectionCost(smallPenalty);
+ }
+ }
+ else if (dim == XDIM)
+ {
+ if (pin->directions() & (ConnDirUp | ConnDirDown))
+ {
+ pin->setConnectionCost(smallPenalty);
+ }
+ }
+ }
+}
+
+
+Point JunctionRef::position(void) const
+{
+ return m_position;
+}
+
+
+void JunctionRef::setPosition(const Point& position)
+{
+ m_position = position;
+ m_recommended_position = position;
+ m_polygon = makeRectangle(m_router, m_position);
+ setNewPoly(m_polygon);
+}
+
+
+Point JunctionRef::recommendedPosition(void) const
+{
+ return m_recommended_position;
+}
+
+
+void JunctionRef::setRecommendedPosition(const Point& position)
+{
+ m_recommended_position = position;
+}
+
+
+void JunctionRef::outputCode(FILE *fp) const
+{
+ fprintf(fp, " JunctionRef *junctionRef%u = new JunctionRef(router, "
+ "Point(%g, %g), %u);\n", id(), position().x, position().y, id());
+ if (m_position_fixed)
+ {
+ fprintf(fp, " junctionRef%u->setPositionFixed(true);\n", id());
+ }
+
+ fprintf(fp, " /*\n");
+ fprintf(fp, " // This may be useful if junction pins are modified.\n");
+ for (ShapeConnectionPinSet::const_iterator curr =
+ m_connection_pins.begin();
+ curr != m_connection_pins.end(); ++curr)
+ {
+ (*curr)->outputCode(fp);
+ }
+ fprintf(fp, " */\n");
+ fprintf(fp, "\n");
+}
+
+
+void JunctionRef::moveAttachedConns(const Point& newPosition)
+{
+ // Update positions of attached connector ends.
+ for (std::set<ConnEnd *>::iterator curr = m_following_conns.begin();
+ curr != m_following_conns.end(); ++curr)
+ {
+ ConnEnd *connEnd = *curr;
+ COLA_ASSERT(connEnd->m_conn_ref != nullptr);
+ m_router->modifyConnector(connEnd->m_conn_ref, connEnd->endpointType(),
+ *connEnd);
+ }
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *pin = *curr;
+ pin->updatePosition(newPosition);
+ }
+}
+
+
+ConnRef *JunctionRef::removeJunctionAndMergeConnectors(void)
+{
+ if (m_following_conns.size() != 2)
+ {
+ return nullptr;
+ }
+
+ std::set<ConnEnd *>::iterator curr = m_following_conns.begin();
+ ConnEnd *connEnd1 = *curr;
+ ++curr;
+ ConnEnd *connEnd2 = *curr;
+ COLA_ASSERT(connEnd2->m_conn_ref != nullptr);
+ COLA_ASSERT(connEnd1->m_conn_ref != nullptr);
+
+ // The second conn will be the one we will delete.
+ ConnRef *conn2 = connEnd2->m_conn_ref;
+ // Determine its endpoint that is not attached to the junction.
+ ConnEnd *connEnd2Other = (conn2->m_src_connend == connEnd2) ?
+ conn2->m_dst_connend : conn2->m_src_connend;
+ if (connEnd2Other == nullptr)
+ {
+ // If it doesn't have a valid other endpoint, then ignore.
+ return nullptr;
+ }
+ // Modify the first connector's junction endpoint to connect to the
+ // other end of the second connector.
+ m_router->modifyConnector(connEnd1->m_conn_ref,
+ connEnd1->endpointType(), *connEnd2Other);
+
+ // Delete the second connector.
+ m_router->deleteConnector(conn2);
+
+ // Remove the junction from the router scene. It should get deleted later.
+ m_router->deleteJunction(this);
+
+ // Return the first (i.e. merged) connector.
+ return connEnd1->m_conn_ref;
+}
+
+
+//============================================================================
+}
+
+