summaryrefslogtreecommitdiffstats
path: root/src/libavoid/router.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libavoid/router.h')
-rw-r--r--src/libavoid/router.h697
1 files changed, 602 insertions, 95 deletions
diff --git a/src/libavoid/router.h b/src/libavoid/router.h
index 03060b025..e7cbd4169 100644
--- a/src/libavoid/router.h
+++ b/src/libavoid/router.h
@@ -3,7 +3,7 @@
*
* libavoid - Fast, Incremental, Object-avoiding Line Router
*
- * Copyright (C) 2004-2009 Monash University
+ * Copyright (C) 2004-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
@@ -19,7 +19,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
- * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Author(s): Michael Wybrow
*/
//! @file router.h
@@ -29,31 +29,41 @@
#ifndef AVOID_ROUTER_H
#define AVOID_ROUTER_H
+#include <ctime>
#include <list>
#include <utility>
#include <string>
-#include "libavoid/shape.h"
-#include "libavoid/viscluster.h"
+#include "libavoid/dllexport.h"
+#include "libavoid/connector.h"
+#include "libavoid/vertices.h"
#include "libavoid/graph.h"
#include "libavoid/timer.h"
-#include "libavoid/connector.h"
-
-#if defined(LINEDEBUG) || defined(ASTAR_DEBUG) || defined(LIBAVOID_SDL)
- #include <SDL.h>
- #ifndef LIBAVOID_SDL
- #define LIBAVOID_SDL
- #endif
-#endif
+#include "libavoid/hyperedge.h"
+#include "libavoid/actioninfo.h"
+#include "libavoid/hyperedgeimprover.h"
namespace Avoid {
+// LineReps: Used for highlighting certain areas in debugging output.
+struct LineRep
+{
+ Point begin;
+ Point end;
+};
+typedef std::list<LineRep> LineReps;
+
+
typedef std::list<unsigned int> IntList;
-class ActionInfo;
-typedef std::list<ActionInfo> ActionInfoList;
class ShapeRef;
+class JunctionRef;
+class ClusterRef;
+typedef std::list<ClusterRef *> ClusterRefList;
+class Obstacle;
+typedef std::list<Obstacle *> ObstacleList;
+class DebugHandler;
//! @brief Flags that can be passed to the router during initialisation
//! to specify options.
@@ -72,15 +82,20 @@ static const unsigned int runningTo = 1;
static const unsigned int runningFrom = 2;
static const unsigned int runningToAndFrom = runningTo | runningFrom;
-//! @brief Types of penalty cases that can be used to improve the quality
-//! of the connector routes produced.
-enum PenaltyType
+//! @brief Types of routing parameters and penalties that can be used to
+//! tailor the style and improve the quality of the connector
+//! routes produced.
+enum RoutingParameter
{
//! @brief This penalty is applied for each segment in the connector
//! path beyond the first. This should always normally be set
//! when doing orthogonal routing to prevent step-like connector
//! paths.
+ //! @note This penalty must be set (i.e., be greater than zero) in
+ //! order for orthogonal connector nudging to be performed, since
+ //! this requires reasonable initial routes.
segmentPenalty = 0,
+
//! @brief This penalty is applied in its full amount to tight acute
//! bends in the connector path. A smaller portion of the penalty
//! is applied for slight bends, i.e., where the bend is close to
@@ -89,6 +104,7 @@ enum PenaltyType
//! readability, but that slight bends might not be so bad,
//! especially when smoothed by curves.
anglePenalty,
+
//! @brief This penalty is applied whenever a connector path crosses
//! another connector path. It takes shared paths into
//! consideration and the penalty is only applied if there
@@ -96,11 +112,16 @@ enum PenaltyType
//! @note This penalty is still experimental! It is not recommended
//! for normal use.
crossingPenalty,
+
//! @brief This penalty is applied whenever a connector path crosses
//! a cluster boundary.
//! @note This penalty is still experimental! It is not recommended
//! for normal use.
+ //! @note This penalty is very slow. You can override the method
+ //! Router::shouldContinueTransactionWithProgress() to check
+ //! progress and possibly cancel overly slow transactions.
clusterCrossingPenalty,
+
//! @brief This penalty is applied whenever a connector path shares
//! some segments with an immovable portion of an existing
//! connector route (such as the first or last segment of a
@@ -108,14 +129,253 @@ enum PenaltyType
//! @note This penalty is still experimental! It is not recommended
//! for normal use.
fixedSharedPathPenalty,
- // Used for determining the size of the penalty array.
+
+ //! @brief This penalty is applied to port selection choice when the
+ //! other end of the connector being routed does not appear in
+ //! any of the 90 degree visibility cones centered on the
+ //! visibility directions for the port.
+ //! @note This penalty is still experimental! It is not recommended
+ //! for normal use.
+ //! @note This penalty is very slow. You can override the method
+ //! Router::shouldContinueTransactionWithProgress() to check
+ //! progress and possibly cancel overly slow transactions.
+ portDirectionPenalty,
+
+ //! @brief This parameter defines the spacing distance that will be added
+ //! to the sides of each shape when determining obstacle sizes for
+ //! routing. This controls how closely connectors pass shapes, and
+ //! can be used to prevent connectors overlapping with shape
+ //! boundaries. By default, this distance is set to a value of 0.
+ shapeBufferDistance,
+
+ //! @brief This parameter defines the spacing distance that will be used
+ //! for nudging apart overlapping corners and line segments of
+ //! connectors. By default, this distance is set to a value of 4.
+ idealNudgingDistance,
+
+ //! @brief This penalty is applied whenever a connector path travels
+ //! in the direction opposite of the destination from the source
+ //! endpoint. By default this penalty is set to zero. This
+ //! shouldn't be needed in most cases but can be useful if you
+ //! use penalties such as ::crossingPenalty which cause connectors
+ //! to loop around obstacles.
+ reverseDirectionPenalty,
+
+ // Used for determining the size of the routing parameter array.
// This should always we the last value in the enum.
- lastPenaltyMarker
+ lastRoutingParameterMarker
};
+// Backwards compatibility
+typedef enum RoutingParameter PenaltyType;
-static const double noPenalty = 0;
-static const double chooseSensiblePenalty = -1;
+
+//! @brief Types of routing options that can be enabled.
+enum RoutingOption
+{
+ //! This option causes the final segments of connectors, which are
+ //! attached to shapes, to be nudged apart. Usually these segments
+ //! are fixed, since they are considered to be attached to ports.
+ //!
+ //! Defaults to false.
+ //!
+ //! This option also causes routes running through the same checkpoint
+ //! to be nudged apart.
+ //!
+ //! This option has no effect if ::nudgeSharedPathsWithCommonEndPoint is
+ //! set to false,
+ //!
+ //! @note This will allow routes to be nudged up to the bounds of shapes.
+ //!
+ nudgeOrthogonalSegmentsConnectedToShapes = 0,
+
+ //! This option causes hyperedge routes to be locally improved fixing
+ //! obviously bad paths. As part of this process libavoid will
+ //! effectively move junctions, setting new ideal positions which can be
+ //! accessed via JunctionRef::recommendedPosition() for each junction.
+ //!
+ //! Defaults to true.
+ //!
+ //! This will not add or remove junctions, so will keep the hyperedge
+ //! topology the same. Better routes can be achieved by enabling the
+ //! ::improveHyperedgeRoutesMovingAddingAndDeletingJunctions option.
+ //!
+ //! If initial sensible positions for junctions in hyperedges are not
+ //! known you can register those hyperedges with the HyperedgeRerouter
+ //! class for complete rerouting.
+ //!
+ //! @sa improveHyperedgeRoutesMovingAddingAndDeletingJunctions
+ //! @sa Router::hyperedgeRerouter()
+ //!
+ improveHyperedgeRoutesMovingJunctions,
+
+ //! This option penalises and attempts to reroute orthogonal shared
+ //! connector paths terminating at a common junction or shape
+ //! connection pin. When multiple connector paths enter or leave
+ //! the same side of a junction (or shape pin), the router will
+ //! attempt to reroute these to different sides of the junction or
+ //! different shape pins.
+ //!
+ //! Defaults to false.
+ //!
+ //! This option depends on the ::fixedSharedPathPenalty penalty having
+ //! been set.
+ //!
+ //! @sa fixedSharedPathPenalty
+ //! @note This option is still experimental! It is not recommended
+ //! for normal use.
+ //!
+ penaliseOrthogonalSharedPathsAtConnEnds,
+
+ //! This option can be used to control whether collinear line
+ //! segments that touch just at their ends will be nudged apart.
+ //! The overlap will usually be resolved in the other dimension,
+ //! so this is not usually required.
+ //!
+ //! Defaults to false.
+ //!
+ nudgeOrthogonalTouchingColinearSegments,
+
+ //! This option can be used to control whether the router performs
+ //! a preprocessing step before orthogonal nudging where is tries
+ //! to unify segments and centre them in free space. This
+ //! generally results in better quality ordering and nudging.
+ //!
+ //! Defaults to true.
+ //!
+ //! You may wish to turn this off for large examples where it
+ //! can be very slow and will make little difference.
+ //!
+ performUnifyingNudgingPreprocessingStep,
+
+ //! This option causes hyperedge routes to be locally improved fixing
+ //! obviously bad paths.
+ //!
+ //! It can cause junctions and connectors to be added or removed from
+ //! hyperedges. To get details of these changes for each connector you can
+ //! call Router::newAndDeletedObjectListsFromHyperedgeImprovement().
+ //!
+ //! As part of this process libavoid will effectively move junctions by
+ //! setting new ideal positions for each remaining or added junction,
+ //! which can be read from JunctionRef::recommendedPosition() for each
+ //! junction.
+ //!
+ //! Defaults to false.
+ //!
+ //! If set, this option overrides the ::improveHyperedgeRoutesMovingJunctions
+ //! option.
+ //!
+ //! If initial sensible positions for junctions in hyperedges are not
+ //! known you can register those hyperedges with the HyperedgeRerouter
+ //! class for complete rerouting.
+ //!
+ //! @sa improveHyperedgeRoutesMovingJunctions
+ //! @sa Router::hyperedgeRerouter()
+ //!
+ improveHyperedgeRoutesMovingAddingAndDeletingJunctions,
+
+ //! This option determines whether intermediate segments of connectors that
+ //! are attached to common endpoints will be nudged apart. Usually these
+ //! segments get nudged apart, but you may want to turn this off if you would
+ //! prefer that entire shared paths terminating at a common end point should
+ //! overlap.
+ //!
+ //! Defaults to true.
+ //!
+ nudgeSharedPathsWithCommonEndPoint,
+
+
+ // Used for determining the size of the routing options array.
+ // This should always we the last value in the enum.
+ lastRoutingOptionMarker
+};
+
+//! @brief Types of routing phases reported by
+//! Router::shouldContinueTransactionWithProgress().
+//!
+//! This phases will occur in the order given here, but each phase may take
+//! varying amounts of time.
+//!
+enum TransactionPhases
+{
+ //! @brief The orthogonal visibility graph is built by conducting a
+ //! scan in each dimension. This is the x-dimension.
+ TransactionPhaseOrthogonalVisibilityGraphScanX = 1,
+ //! @brief The orthogonal visibility graph is built by conducting a
+ //! scan in each dimension. This is the y-dimension.
+ TransactionPhaseOrthogonalVisibilityGraphScanY,
+ //! @brief Initial routes are searched for in the visibility graph.
+ TransactionPhaseRouteSearch,
+ //! @brief With crossing penalties enabled, crossing detection is
+ //! performed to find all crossings.
+ TransactionPhaseCrossingDetection,
+ //! @brief Crossing connectors are rerouted to search for better routes.
+ TransactionPhaseRerouteSearch,
+ //! @brief Orthogonal edge segments are nudged apart in the x-dimension.
+ TransactionPhaseOrthogonalNudgingX,
+ //! @brief Orthogonal edge segments are nudged apart in the y-dimension.
+ TransactionPhaseOrthogonalNudgingY,
+ //! @brief Not a real phase, but represents the router is finished (or has
+ //! aborted) the transaction and you may interact with is again.
+ TransactionPhaseCompleted
+};
+
+// NOTE: This is an internal helper class that should not be used by the user.
+//
+// This class allows edges in the visibility graph to store a
+// pointer to a boolean registering when a connector needs to
+// reroute, while allowing connectors to be deleted without
+// needing to scan and remove these references from the visibility
+// graph. Instead the bool is stored in this delegate and the
+// connector is alerted later, so long as it hasn't since been
+// deleted.
+class ConnRerouteFlagDelegate {
+ public:
+ ConnRerouteFlagDelegate();
+ ~ConnRerouteFlagDelegate();
+ bool *addConn(ConnRef *conn);
+ void removeConn(ConnRef *conn);
+ void alertConns(void);
+ private:
+ std::list<std::pair<ConnRef *, bool> > m_mapping;
+};
+
+static const double zeroParamValue = 0;
+static const double chooseSensibleParamValue = -1;
+
+// NOTE: This is an internal helper class that should not be used by the user.
+//
+// It is used by libtopology to add additional functionality to libavoid
+// while keeping libavoid dependency free.
+class TopologyAddonInterface
+{
+ public:
+ TopologyAddonInterface()
+ {
+ }
+ virtual ~TopologyAddonInterface()
+ {
+ }
+ virtual TopologyAddonInterface *clone(void) const
+ {
+ return new TopologyAddonInterface(*this);
+ }
+
+ virtual void improveOrthogonalTopology(Router *router)
+ {
+ (void)(router); // Avoid unused parameter warning.
+ }
+ virtual bool outputCode(FILE *fp) const
+ {
+ (void)(fp); // Avoid unused parameter warning.
+ return false;
+ }
+ virtual bool outputDeletionCode(FILE *fp) const
+ {
+ (void)(fp); // Avoid unused parameter warning.
+ return false;
+ }
+};
//! @brief The Router class represents a libavoid router instance.
@@ -123,7 +383,7 @@ static const double chooseSensiblePenalty = -1;
//! Usually you would keep a separate Router instance for each diagram
//! or layout you have open in your application.
//
-class Router {
+class AVOID_EXPORT Router {
public:
//! @brief Constructor for router instance.
//!
@@ -136,9 +396,9 @@ class Router {
//! @note Destroying a router instance will delete all remaining
//! shapes and connectors, thereby invalidating any existing
//! pointers to them.
- ~Router();
+ virtual ~Router();
- ShapeRefList shapeRefs;
+ ObstacleList m_obstacles;
ConnRefList connRefs;
ClusterRefList clusterRefs;
EdgeList visGraph;
@@ -165,15 +425,14 @@ class Router {
// Instrumentation:
+#ifdef AVOID_PROFILE
Timer timers;
- int st_checked_edges;
-#ifdef LIBAVOID_SDL
- SDL_Surface *avoid_screen;
#endif
+ int st_checked_edges;
//! @brief Allows setting of the behaviour of the router in regard
//! to transactions. This controls whether transactions are
- //! used to queue changes and process them effeciently at once
+ //! used to queue changes and process them efficiently at once
//! or they are instead processed immediately.
//!
//! It is more efficient to perform actions like shape movement,
@@ -183,7 +442,7 @@ class Router {
//! "transactions" that are processed efficiently when the
//! processTransaction() method is called.
//!
- //! By default, the router will process all actions as tranactions.
+ //! By default, the router will process all actions as transactions.
//! If transactionUse() is set to false, then all actions will get
//! processed immediately, and cause immediate routing callbacks to
//! all affected connectors after each action.
@@ -218,25 +477,22 @@ class Router {
//! @sa setTransactionUse
//!
bool processTransaction(void);
-
- //! @brief Add a shape to the router scene.
- //!
- //! This shape will be considered to be an obstacle. Calling this
- //! method will cause connectors intersecting the added shape to
- //! be marked as needing to be rerouted.
- //!
- //! @param[in] shape Pointer reference to the shape being added.
- //!
- void addShape(ShapeRef *shape);
- //! @brief Remove a shape from the router scene.
+ //! @brief Delete a shape from the router scene.
//!
//! Connectors that could have a better (usually shorter) path after
//! the removal of this shape will be marked as needing to be rerouted.
//!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! You should not use the shape reference again after this call.
+ //! The router will handle freeing of the shape's memory.
+ //!
//! @param[in] shape Pointer reference to the shape being removed.
//!
- void removeShape(ShapeRef *shape);
+ void deleteShape(ShapeRef *shape);
//! @brief Move or resize an existing shape within the router scene.
//!
@@ -245,6 +501,10 @@ class Router {
//! new shape polygon, or that could have a better (usually shorter)
//! path after the change, will be marked as needing to be rerouted.
//!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
//! @param[in] shape Pointer reference to the shape being
//! moved/resized.
//! @param[in] newPoly The new polygon boundary for the shape.
@@ -262,6 +522,10 @@ class Router {
//! have a better (usually shorter) path after the change, will be
//! marked as needing to be rerouted.
//!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
//! @param[in] shape Pointer reference to the shape being moved.
//! @param[in] xDiff The distance to move the shape in the
//! x dimension.
@@ -270,83 +534,311 @@ class Router {
//!
void moveShape(ShapeRef *shape, const double xDiff, const double yDiff);
- //! @brief Sets a spacing distance for overlapping orthogonal
- //! connectors to be nudged apart.
+ //! @brief Remove a junction from the router scene.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! You should not use the junction reference again after this call.
+ //! The router will handle freeing of the junction's memory.
+ //!
+ //! @param[in] junction Pointer reference to the junction being
+ //! removed.
+ //!
+ void deleteJunction(JunctionRef *junction);
+
+ //! @brief Remove a connector from the router scene.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! You should not use the connector reference again after this call.
+ //! The router will handle freeing of the connector's memory.
+ //!
+ //! @param[in] connector Pointer reference to the connector being
+ //! removed.
+ //!
+ void deleteConnector(ConnRef *connector);
+
+ //! @brief Move an existing junction within the router scene.
+ //!
+ //! Connectors that are attached to this junction will be rerouted
+ //! as a result of the move.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] junction Pointer reference to the junction being
+ //! moved.
+ //! @param[in] newPosition The new position for the junction.
+ //!
+ void moveJunction(JunctionRef *junction, const Point& newPosition);
+
+ //! @brief Move an existing junction within the router scene by a
+ //! relative distance.
//!
- //! By default, this distance is set to a value of 4.
+ //! Connectors that are attached to this junction will be rerouted
+ //! as a result of the move.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] junction Pointer reference to the junction being
+ //! moved.
+ //! @param[in] xDiff The distance to move the junction in the
+ //! x dimension.
+ //! @param[in] yDiff The distance to move the junction in the
+ //! y dimension.
+ //!
+ void moveJunction(JunctionRef *junction, const double xDiff,
+ const double yDiff);
+
+ //! @brief Sets values for routing parameters, including routing
+ //! penalties.
+ //!
+ //! libavoid uses a set of parameters to allow the user more control
+ //! over routing style and quality. These different parameters are
+ //! described and explained by the RoutingParameter enum. All
+ //! parameters have sensible defaults.
+ //!
+ //! Regarding routing penalties, libavoid will by default produce
+ //! shortest path routes between the source and destination points
+ //! for each connector. There are several penalties that can be
+ //! applied during this stage to penalise certain conditions and
+ //! thus improve the aesthetics of the routes generated.
+ //!
+ //! If a value of zero or Avoid::zeroParamValue is given then the
+ //! particular parameter value or penalty will be removed. If no
+ //! parameter value argument (or a negative value) is specified
+ //! when calling this method, then a sensible penalty value will
+ //! be automatically chosen.
+ //!
+ //! This method does not re-trigger processing of connectors. The new
+ //! parameter value will be used the next time rerouting is performed.
+ //!
+ //! @param[in] parameter The type of penalty, a RoutingParameter.
+ //! @param[in] value The value to be set for that parameter.
//!
- //! This method does not re-trigger post-processing of connectors.
- //! The new distance will be used the next time rerouting is performed.
+ void setRoutingParameter(const RoutingParameter parameter,
+ const double value = chooseSensibleParamValue);
+
+ //! @brief Returns the current value for a particular routing
+ //! parameter of a given type.
+ //!
+ //! @param[in] parameter The type of parameter, a RoutingParameter.
+ //! @return The value for the specified routing parameter.
+ //!
+ double routingParameter(const RoutingParameter parameter) const;
+
+ //! @brief Turn specific routing options on or off.
//!
- //! @param[in] dist The distance to be used for orthogonal nudging.
+ //! @param[in] option The type of routing option, a RoutingOption.
+ //! @param[in] value A boolean representing the option state.
//!
- void setOrthogonalNudgeDistance(const double dist);
+ void setRoutingOption(const RoutingOption option, const bool value);
- //! @brief Returns the spacing distance that overlapping orthogonal
- //! connecotrs are nudged apart.
+ //! @brief Returns the current state for a specific routing option.
//!
- //! @return The current spacing distance used for orthogonal nudging.
+ //! @param[in] option The type of routing option, a RoutingOption.
+ //! @return A boolean representing the option state.
//!
- double orthogonalNudgeDistance(void) const;
+ bool routingOption(const RoutingOption option) const;
//! @brief Sets or removes penalty values that are applied during
//! connector routing.
//!
- //! By default, libavoid will produce shortest path routes between
- //! the source and destination points for each connector. There are
- //! several penalties that can be applied during this stage to
- //! improve the aesthetics of the routes generated. These different
- //! penalties are specified and explained by the PenaltyType enum.
- //!
- //! If a value of zero or Avoid::noPenalty is given then the penalty
- //! for this case will be removed. If no penalty argument (or a
- //! negative value) is specified when calling this method, then a
- //! sensible penalty value will be automatically chosen.
+ //! @note This is a convenience wrapper for the setRoutingParameter()
+ // method. See its documentation for more details.
//!
- //! @param[in] penType The type of penalty, a PenaltyType.
- //! @param[in] penVal The value to be applied for each occurance
+ //! @param[in] penType The type of penalty, a RoutingParameter.
+ //! @param[in] penVal The value to be applied for each occurrence
//! of the penalty case.
//!
- void setRoutingPenalty(const PenaltyType penType,
- const double penVal = chooseSensiblePenalty);
+ void setRoutingPenalty(const RoutingParameter penType,
+ const double penVal = chooseSensibleParamValue);
- //! @brief Returns the current penalty value for a particular
- //! routing penalty case.
+ //! @brief Returns a pointer to the hyperedge rerouter for the router.
//!
- //! @param[in] penType The type of penalty, a PenaltyType.
- //! @return The penalty value for the specified penalty case.
+ //! @return A HyperedgeRerouter object that can be used to register
+ //! hyperedges for rerouting.
//!
- double routingPenalty(const PenaltyType penType) const;
+ HyperedgeRerouter *hyperedgeRerouter(void);
- void addCluster(ClusterRef *cluster);
- void delCluster(ClusterRef *cluster);
+ //! @brief Generates an SVG file containing debug output and code that
+ //! can be used to regenerate the instance.
+ //!
+ //! If transactions are being used, then this method should be called
+ //! after processTransaction() has been called, so that it includes any
+ //! changes being queued by the router.
+ //!
+ //! @param[in] filename A string indicating the filename (without
+ //! extension) for the output file. Defaults to
+ //! "libavoid-debug.svg" if no filename is given.
+ //!
+ void outputInstanceToSVG(std::string filename = std::string());
- void attachedConns(IntList &conns, const unsigned int shapeId,
- const unsigned int type);
+ //! @brief Returns the object ID used for automatically generated
+ //! objects, such as during hyperedge routing.
+ //!
+ //! Reimplement this in a subclass to set specific IDs for new objects.
+ //!
+ //! @note Your implementation should return a value that does not
+ //! fail objectIdIsUnused().
+ //!
+ //! @return The ID for a new object.
+ //!
+ virtual unsigned int newObjectId(void) const;
+
+ //! @brief Returns whether or not the given ID is already used.
+ //!
+ //! You should only need this if you reimplement newObjectId().
+ //!
+ //! @param[in] id An ID to test.
+ //! @return A boolean denoting that the given ID is unused.
+ //!
+ bool objectIdIsUnused(const unsigned int id) const;
+
+ //! @brief A method called at regular intervals during transaction
+ //! processing to report progress and ask if the Router
+ //! should continue the transaction.
+ //!
+ //! You can subclass the Avoid::Router class to implement your
+ //! own behaviour, such as to show a progress bar or cancel the
+ //! transaction at the user's request.
+ //!
+ //! Note that you can get a sense of progress by looking at the
+ //! phaseNumber divided by the totalPhases and the progress in the
+ //! current phase, but be aware that phases and the intervals and
+ //! proportions at which this method is called will vary, sometime
+ //! unpredictably.
+ //!
+ //! You can return false to request that the Router abort the current
+ //! transaction. Be aware that it may not abort in some phases. For
+ //! others it may need to clean up some state before it is safe for
+ //! you to interact with it again. Hence you should wait for a final
+ //! call to this method with the phase Avoid::TransactionPhaseCompleted
+ //! before continuing.
+ //!
+ //! @note Your implementation of this method should be very fast as
+ //! it will be called many times. Also, you should not change
+ //! or interact with the Router instance at all during these
+ //! calls. Wait till you have received a call with the
+ //! Avoid::TransactionPhaseCompleted phase.
+ //!
+ //! @param elapsedTime The number of msec spent on the transaction
+ //! since it began.
+ //! @param phaseNumber A Router::TransactionPhases representing the
+ //! current phase of the transaction.
+ //! @param totalPhases The total number of phases to be performed
+ //! during the transaction.
+ //! @param proportion A double representing the progress in the
+ //! current phase. Value will be between 0--1.
+ //!
+ //! @return Whether the router should continue the transaction.
+ //! This is true in the default (empty) implementation.
+ virtual bool shouldContinueTransactionWithProgress(
+ unsigned int elapsedTime, unsigned int phaseNumber,
+ unsigned int totalPhases, double proportion);
+
+ //! @brief Returns a HyperedgeNewAndDeletedObjectLists detailing the
+ //! lists of junctions and connectors created and deleted
+ //! during hyperedge improvement.
+ //!
+ //! This method will only return information once the router has
+ //! processed the transaction. You should read and act on this
+ //! information before processTransaction() is called again.
+ //!
+ //! After calling this you should no longer refer to any of the
+ //! objects in the "deleted" lists --- the router will delete these
+ //! and free their memory at its convenience.
+ //!
+ //! @return A HyperedgeNewAndDeletedObjectLists containing lists of
+ //! junctions and connectors created and deleted.
+ //!
+ HyperedgeNewAndDeletedObjectLists
+ newAndDeletedObjectListsFromHyperedgeImprovement(void) const;
+
+ void setDebugHandler(DebugHandler *handler);
+ DebugHandler *debugHandler(void) const;
+
+ // Processes the actions list for the transaction. You shouldn't
+ // need to cal this. Instead use processTransaction().
+ void processActions(void);
+
+ void deleteCluster(ClusterRef *cluster);
void attachedShapes(IntList &shapes, const unsigned int shapeId,
const unsigned int type);
-
- void markConnectors(ShapeRef *shape);
+ void attachedConns(IntList &conns, const unsigned int shapeId,
+ const unsigned int type);
+ void markPolylineConnectorsNeedingReroutingForDeletedObstacle(
+ Obstacle *obstacle);
void generateContains(VertInf *pt);
void printInfo(void);
- void outputInstanceToSVG(std::string filename = std::string());
- unsigned int assignId(const unsigned int suggestedId);
void regenerateStaticBuiltGraph(void);
void destroyOrthogonalVisGraph(void);
void setStaticGraphInvalidated(const bool invalidated);
ConnType validConnType(const ConnType select = ConnType_None) const;
- bool shapeInQueuedActionList(ShapeRef *shape) const;
- double& penaltyRef(const PenaltyType penType);
- bool existsOrthogonalPathOverlap(void);
- bool existsOrthogonalTouchingCorners(void);
+ bool isInCrossingPenaltyReroutingStage(void) const;
+ void markAllObstaclesAsMoved(void);
+ ShapeRef *shapeContainingPoint(const Point& point);
+ void performContinuationCheck(unsigned int phaseNumber,
+ size_t stepNumber, size_t totalSteps);
+ void registerSettingsChange(void);
+
+ /**
+ * @brief Set an addon for doing orthogonal topology improvement.
+ *
+ * It is expected that you would use the topology::AvoidTopologyAddon()
+ * from libtopology rather than write your own. This is done so that
+ * libavoid does not have to depend on libtopology.
+ */
+ void setTopologyAddon(TopologyAddonInterface *topologyAddon);
+ void improveOrthogonalTopology(void);
+
+ // Testing and debugging methods.
+ bool existsOrthogonalSegmentOverlap(const bool atEnds = false);
+ bool existsOrthogonalFixedSegmentOverlap(const bool atEnds = false);
+ bool existsOrthogonalTouchingPaths(void);
+ int existsCrossings(const bool optimisedForConnectorType = false);
+ bool existsInvalidOrthogonalPaths(void);
+
+ // Outputs the current diagram. Used for visualising individual
+ // steps of various algorithms. lineReps can be used to draw
+ // attention to specific parts of the diagram that have changed
+ // between steps.
+ void outputDiagramSVG(std::string instanceName = std::string(),
+ LineReps *lineReps = NULL);
+
+ void outputDiagramText(std::string instanceName = std::string());
+ void outputDiagram(std::string instanceName = std::string());
private:
+ friend class ShapeRef;
friend class ConnRef;
+ friend class JunctionRef;
+ friend class Obstacle;
+ friend class ClusterRef;
+ friend class ShapeConnectionPin;
+ friend class MinimumTerminalSpanningTree;
+ friend class ConnEnd;
+ friend struct HyperedgeTreeNode;
+ friend class HyperedgeRerouter;
+ friend class HyperedgeImprover;
+ unsigned int assignId(const unsigned int suggestedId);
+ void addShape(ShapeRef *shape);
+ void addJunction(JunctionRef *junction);
+ void addCluster(ClusterRef *cluster);
void modifyConnector(ConnRef *conn);
void modifyConnector(ConnRef *conn, unsigned int type,
- const ConnEnd &connEnd);
- void removeQueuedConnectorActions(ConnRef *conn);
+ const ConnEnd &connEnd, bool connPinUpdate = false);
+ void modifyConnectionPin(ShapeConnectionPin *pin);
+
+ void removeObjectFromQueuedActions(const void *object);
void newBlockingShape(const Polygon& poly, int pid);
void checkAllBlockedEdges(int pid);
void checkAllMissingEdges(void);
@@ -356,24 +848,39 @@ class Router {
const int p_cluster);
void adjustClustersWithDel(const int p_cluster);
void rerouteAndCallbackConnectors(void);
- bool idIsUnique(const unsigned int id) const;
void improveCrossings(void);
ActionInfoList actionList;
- unsigned int _largestAssignedId;
- bool _consolidateActions;
- double _orthogonalNudgeDistance;
- double _routingPenalties[lastPenaltyMarker];
+ unsigned int m_largest_assigned_id;
+ bool m_consolidate_actions;
+ bool m_currently_calling_destructors;
+ double m_routing_parameters[lastRoutingParameterMarker];
+ bool m_routing_options[lastRoutingOptionMarker];
+
+ ConnRerouteFlagDelegate m_conn_reroute_flags;
+ HyperedgeRerouter m_hyperedge_rerouter;
+
+ // Progress tracking and transaction cancelling.
+ clock_t m_transaction_start_time;
+ bool m_abort_transaction;
+
+ TopologyAddonInterface *m_topology_addon;
- public:
// Overall modes:
- bool _polyLineRouting;
- bool _orthogonalRouting;
+ bool m_allows_polyline_routing;
+ bool m_allows_orthogonal_routing;
+
+ bool m_static_orthogonal_graph_invalidated;
+ bool m_in_crossing_rerouting_stage;
+
+ bool m_settings_changes;
+
+ HyperedgeImprover m_hyperedge_improver;
- bool _staticGraphInvalidated;
- bool _inCrossingPenaltyReroutingStage;
+ DebugHandler *m_debug_handler;
};
+
}