From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/3rdparty/adaptagrams/libavoid/connend.cpp | 435 ++++++++++++++++++++++++++ 1 file changed, 435 insertions(+) create mode 100644 src/3rdparty/adaptagrams/libavoid/connend.cpp (limited to 'src/3rdparty/adaptagrams/libavoid/connend.cpp') diff --git a/src/3rdparty/adaptagrams/libavoid/connend.cpp b/src/3rdparty/adaptagrams/libavoid/connend.cpp new file mode 100644 index 0000000..7a5f6c1 --- /dev/null +++ b/src/3rdparty/adaptagrams/libavoid/connend.cpp @@ -0,0 +1,435 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libavoid - Fast, Incremental, Object-avoiding Line Router + * + * Copyright (C) 2004-2009 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 +#include +#include +#include +#include + +#include "libavoid/router.h" +#include "libavoid/connend.h" +#include "libavoid/connector.h" +#include "libavoid/connectionpin.h" +#include "libavoid/junction.h" +#include "libavoid/shape.h" +#include "libavoid/debug.h" +#include "libavoid/graph.h" +#include "libavoid/visibility.h" + +namespace Avoid { + + +ConnEnd::ConnEnd() + : m_type(ConnEndEmpty), + m_point(Point(0,0)), + m_directions(ConnDirAll), + m_connection_pin_class_id(CONNECTIONPIN_UNSET), + m_anchor_obj(nullptr), + m_conn_ref(nullptr), + m_active_pin(nullptr) +{ +} + +ConnEnd::ConnEnd(const Point& point) + : m_type(ConnEndPoint), + m_point(point), + m_directions(ConnDirAll), + m_connection_pin_class_id(CONNECTIONPIN_UNSET), + m_anchor_obj(nullptr), + m_conn_ref(nullptr), + m_active_pin(nullptr) +{ +} + + +ConnEnd::ConnEnd(const Point& point, const ConnDirFlags visDirs) + : m_type(ConnEndPoint), + m_point(point), + m_directions(visDirs), + m_connection_pin_class_id(CONNECTIONPIN_UNSET), + m_anchor_obj(nullptr), + m_conn_ref(nullptr), + m_active_pin(nullptr) +{ +} + + +ConnEnd::ConnEnd(ShapeRef *shapeRef, const unsigned int connectionPinClassID) + : m_type(ConnEndShapePin), + m_point(Point(0,0)), + m_directions(ConnDirAll), + m_connection_pin_class_id(connectionPinClassID), + m_anchor_obj(shapeRef), + m_conn_ref(nullptr), + m_active_pin(nullptr) +{ + COLA_ASSERT(m_anchor_obj != nullptr); + COLA_ASSERT(m_connection_pin_class_id > 0); + + m_point = m_anchor_obj->position(); + COLA_ASSERT(m_connection_pin_class_id != CONNECTIONPIN_UNSET); +} + + +ConnEnd::ConnEnd(JunctionRef *junctionRef) + : m_type(ConnEndJunction), + m_directions(ConnDirAll), + m_connection_pin_class_id(CONNECTIONPIN_CENTRE), + m_anchor_obj(junctionRef), + m_conn_ref(nullptr), + m_active_pin(nullptr) +{ + COLA_ASSERT(m_anchor_obj != nullptr); + m_point = m_anchor_obj->position(); +} + + +ConnEnd::~ConnEnd() +{ +} + + +ConnEndType ConnEnd::type(void) const +{ + return m_type; +} + + +const Point ConnEnd::position(void) const +{ + if (m_active_pin) // Attached to a pin! + { + return m_active_pin->position(); + } + else if (m_anchor_obj) + { + return m_anchor_obj->position(); + } + else + { + return m_point; + } +} + + +ConnDirFlags ConnEnd::directions(void) const +{ + if (m_active_pin) // Attached to a pin! + { + return m_active_pin->directions(); + } + else + { + return m_directions; + } +} + + +ShapeRef *ConnEnd::shape(void) const +{ + return dynamic_cast (m_anchor_obj); +} + + +JunctionRef *ConnEnd::junction(void) const +{ + return dynamic_cast (m_anchor_obj); +} + + +unsigned int ConnEnd::pinClassId(void) const +{ + return m_connection_pin_class_id; +} + + + +bool ConnEnd::isPinConnection(void) const +{ + return (m_type == ConnEndShapePin) || (m_type == ConnEndJunction); +} + +unsigned int ConnEnd::endpointType(void) const +{ + COLA_ASSERT(m_conn_ref != nullptr); + return (m_conn_ref->m_dst_connend == this) ? VertID::tar : VertID::src; +} + + +// Marks this ConnEnd as using a particular ShapeConnectionPin. +void ConnEnd::usePin(ShapeConnectionPin *pin) +{ + COLA_ASSERT(m_active_pin == nullptr); + + m_active_pin = pin; + if (m_active_pin) + { + m_active_pin->m_connend_users.insert(this); + } +} + + +// Marks this ConnEnd as using a particular ShapeConnectionPin's vertex. +void ConnEnd::usePinVertex(VertInf *pinVert) +{ + COLA_ASSERT(m_active_pin == nullptr); + + for (ShapeConnectionPinSet::iterator curr = + m_anchor_obj->m_connection_pins.begin(); + curr != m_anchor_obj->m_connection_pins.end(); ++curr) + { + ShapeConnectionPin *currPin = *curr; + if (currPin->m_vertex == pinVert) + { + usePin(currPin); + break; + } + } +} + + +// Returns a vector of the possible Points for this ConnEnd +std::vector ConnEnd::possiblePinPoints(void) const +{ + std::vector points; + if (!m_anchor_obj || (m_connection_pin_class_id == CONNECTIONPIN_UNSET)) + { + return points; + } + + return m_anchor_obj->possiblePinPoints(m_connection_pin_class_id); +} + +// Marks this ConnEnd as no longer using the active ShapeConnectionPin +void ConnEnd::freeActivePin(void) +{ + if (m_active_pin) + { + m_active_pin->m_connend_users.erase(this); + } + m_active_pin = nullptr; +} + + +// Creates the connection between a connector and a shape/junction. +void ConnEnd::connect(ConnRef *conn) +{ + COLA_ASSERT(isPinConnection()); + COLA_ASSERT(m_anchor_obj); + COLA_ASSERT(m_conn_ref == nullptr); + + m_anchor_obj->addFollowingConnEnd(this); + m_conn_ref = conn; +} + + +// Removes the connection between a connector and a shape/junction. +void ConnEnd::disconnect(const bool shapeDeleted) +{ + if (m_conn_ref == nullptr) + { + // Not connected. + return; + } + + m_point = position(); + m_anchor_obj->removeFollowingConnEnd(this); + m_conn_ref = nullptr; + + if (shapeDeleted) + { + // Turn this into a manual ConnEnd. + m_point = position(); + m_anchor_obj = nullptr; + m_type = ConnEndPoint; + m_connection_pin_class_id = CONNECTIONPIN_UNSET; + } +} + + +// Assign visibility to a dummy vertex representing all the possible pins +// for this pinClassId. +void ConnEnd::assignPinVisibilityTo(VertInf *dummyConnectionVert, + VertInf *targetVert) +{ + unsigned int validPinCount = 0; + + COLA_ASSERT(m_anchor_obj); + COLA_ASSERT(m_connection_pin_class_id != CONNECTIONPIN_UNSET); + + Router *router = m_anchor_obj->router(); + for (ShapeConnectionPinSet::iterator curr = + m_anchor_obj->m_connection_pins.begin(); + curr != m_anchor_obj->m_connection_pins.end(); ++curr) + { + ShapeConnectionPin *currPin = *curr; + if ((currPin->m_class_id == m_connection_pin_class_id) && + (!currPin->m_exclusive || currPin->m_connend_users.empty())) + { + double routingCost = currPin->m_connection_cost; + Point adjTargetPt = targetVert->point - currPin->m_vertex->point; + double angle = rotationalAngle(adjTargetPt); + bool inVisibilityRange = false; + + if (angle <= 45 || angle >= 315) + { + if (currPin->directions() & ConnDirRight) + { + inVisibilityRange = true; + } + } + if (angle >= 45 && angle <= 135) + { + if (currPin->directions() & ConnDirDown) + { + inVisibilityRange = true; + } + } + if (angle >= 135 && angle <= 225) + { + if (currPin->directions() & ConnDirLeft) + { + inVisibilityRange = true; + } + } + if (angle >= 225 && angle <= 315) + { + if (currPin->directions() & ConnDirUp) + { + inVisibilityRange = true; + } + } + if (!inVisibilityRange) + { + routingCost += router->routingParameter(portDirectionPenalty); + } + + if (router->m_allows_orthogonal_routing) + { + // This has same ID and is either unconnected or not + // exclusive, so give it visibility. + EdgeInf *edge = new EdgeInf(dummyConnectionVert, + currPin->m_vertex, true); + // XXX Can't use a zero cost due to assumptions + // elsewhere in code. + edge->setDist(manhattanDist(dummyConnectionVert->point, + currPin->m_vertex->point) + + std::max(0.001, routingCost)); + } + + if (router->m_allows_polyline_routing) + { + // This has same ID and is either unconnected or not + // exclusive, so give it visibility. + EdgeInf *edge = new EdgeInf(dummyConnectionVert, + currPin->m_vertex, false); + // XXX Can't use a zero cost due to assumptions + // elsewhere in code. + edge->setDist(euclideanDist(dummyConnectionVert->point, + currPin->m_vertex->point) + + std::max(0.001, routingCost)); + } + + // Increment the number of valid pins for this ConnEnd connection. + validPinCount++; + } + } + + if (validPinCount == 0) + { + // There should be at least one pin, otherwise we will have + // problems finding connector routes. + err_printf("Warning: In ConnEnd::assignPinVisibilityTo():\n" + " ConnEnd for connector %d can't connect to shape %d\n" + " since it has no pins with class id of %u.\n", + (int) m_conn_ref->id(), (int) m_anchor_obj->id(), + m_connection_pin_class_id); + } +} + + +std::pair ConnEnd::getHyperedgeVertex(Router *router) const +{ + bool addedVertex = false; + VertInf *vertex = nullptr; + + if (m_anchor_obj) + { + for (ShapeConnectionPinSet::iterator curr = + m_anchor_obj->m_connection_pins.begin(); + curr != m_anchor_obj->m_connection_pins.end(); ++curr) + { + ShapeConnectionPin *currPin = *curr; + if ((currPin->m_class_id == m_connection_pin_class_id) && + (!currPin->m_exclusive || currPin->m_connend_users.empty())) + { + vertex = currPin->m_vertex; + } + } + COLA_ASSERT(vertex != nullptr); + } + else + { + VertID id(0, kUnassignedVertexNumber, + VertID::PROP_ConnPoint); + vertex = new VertInf(router, id, m_point); + vertex->visDirections = m_directions; + addedVertex = true; + + if (router->m_allows_polyline_routing) + { + vertexVisibility(vertex, nullptr, true, true); + } + } + + return std::make_pair(addedVertex, vertex); +} + + +void ConnEnd::outputCode(FILE *fp, const char *srcDst) const +{ + if (junction()) + { + fprintf(fp, " %sPt = ConnEnd(junctionRef%u);\n", srcDst, + m_anchor_obj->id()); + } + else if (shape()) + { + fprintf(fp, " %sPt = ConnEnd(shapeRef%u, %u);\n", srcDst, + m_anchor_obj->id(), m_connection_pin_class_id); + } + else + { + fprintf(fp, " %sPt = ConnEnd(Point(%" PREC "g, %" PREC "g), (ConnDirFlags) %u);\n", + srcDst, m_point.x, m_point.y, m_directions); + } +} + + +//============================================================================ + +} + + -- cgit v1.2.3