X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Flibavoid%2Fconnector.h;h=8f7499a2934838709479ec325a87d5a18713761c;hb=42b53baed61b6b06f33ecfa440a747382eb350df;hp=64afb4dda7f9abe698031613d687ac7522f692d7;hpb=58b01d0739d26b3257ff197b4c34d3fb738b1534;p=inkscape.git diff --git a/src/libavoid/connector.h b/src/libavoid/connector.h index 64afb4dda..8f7499a29 100644 --- a/src/libavoid/connector.h +++ b/src/libavoid/connector.h @@ -2,93 +2,336 @@ * vim: ts=4 sw=4 et tw=0 wm=0 * * libavoid - Fast, Incremental, Object-avoiding Line Router - * Copyright (C) 2004-2006 Michael Wybrow + * + * 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. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Author(s): Michael Wybrow */ +//! @file shape.h +//! @brief Contains the interface for the ConnRef class. + + #ifndef AVOID_CONNECTOR_H #define AVOID_CONNECTOR_H -#include "libavoid/router.h" +#include +#include + +#include "libavoid/vertices.h" #include "libavoid/geometry.h" #include "libavoid/shape.h" -#include namespace Avoid { +class Router; +class ConnRef; +typedef std::list ConnRefList; + + +//! @brief Describes the type of routing that is performed for each +//! connector. +enum ConnType { + ConnType_None = 0, + //! @brief The connector path will be a shortest-path poly-line that + //! routes around obstacles. + ConnType_PolyLine = 1, + //! @brief The connector path will be a shortest-path orthogonal + //! poly-line (only vertical and horizontal line segments) that + //! routes around obstacles. + ConnType_Orthogonal = 2 +}; + +//! @brief Flags that can be passed to the ConnEnd constructor to specify +//! which sides of a shape this point should have visibility to if +//! it is located within the shape's area. +//! +//! Like SVG, libavoid considers the Y-axis to point downwards, that is, +//! like screen coordinates the coordinates increase from left-to-right and +//! also from top-to-bottom. +//! +enum ConnDirFlag { + ConnDirNone = 0, + //! @brief This option specifies the point should be given visibility + //! to the top of the shape that it is located within. + ConnDirUp = 1, + //! @brief This option specifies the point should be given visibility + //! to the bottom of the shape that it is located within. + ConnDirDown = 2, + //! @brief This option specifies the point should be given visibility + //! to the left side of the shape that it is located within. + ConnDirLeft = 4, + //! @brief This option specifies the point should be given visibility + //! to the right side of the shape that it is located within. + ConnDirRight = 8, + //! @brief This option, provided for convenience, specifies the point + //! should be given visibility to all four sides of the shape + //! that it is located within. + ConnDirAll = 15 +}; +//! @brief One or more Avoid::ConnDirFlag options. +//! +typedef unsigned int ConnDirFlags; + + +static const double ATTACH_POS_TOP = 0; +static const double ATTACH_POS_CENTER = 0.5; +static const double ATTACH_POS_BOTTOM = 1; +static const double ATTACH_POS_LEFT = ATTACH_POS_TOP; +static const double ATTACH_POS_RIGHT = ATTACH_POS_BOTTOM; + + +//! @brief The ConnEnd class represents different possible endpoints for +//! connectors. +//! +//! Currently this class just allows free-floating endpoints, but in future +//! will be capable of representing attachments to connection points on shapes. +//! +class ConnEnd +{ + public: + //! @brief Constructs a ConnEnd from a free-floating point. + //! + //! @param[in] point The position of the connector endpoint. + //! + ConnEnd(const Point& point); + + //! @brief Constructs a ConnEnd from a free-floating point as well + //! as a set of flags specifying visibility for this point + //! if it is located inside a shape. + //! + //! @param[in] point The position of the connector endpoint. + //! @param[in] visDirs One or more Avoid::ConnDirFlag options + //! specifying the directions that this point + //! should be given visibility if it is inside + //! a shape. + //! + ConnEnd(const Point& point, const ConnDirFlags visDirs); + + ConnEnd(ShapeRef *shapeRef, const double x_pos, const double y_pos, + const double insideOffset = 0.0, + const ConnDirFlags visDirs = ConnDirNone); -static const int ConnType_PolyLine = 1; -static const int ConnType_Orthogonal = 2; + //! @brief Returns the position of this connector endpoint + //! + //! @return The position of this connector endpoint. + const Point point(void) const; + + ConnDirFlags directions(void) const; + private: + Point _point; + ConnDirFlags _directions; + + // For referencing ConnEnds + ShapeRef *_shapeRef; + double _xPosition; + double _yPosition; + double _insideOffset; +}; +//! @brief The ConnRef class represents a connector object. +//! +//! Connectors are a (possible multi-segment) line between two points. +//! They are routed intelligently so as not to overlap any of the shape +//! objects in the Router scene. +//! +//! Routing penalties can be applied, resulting in more aesthetically pleasing +//! connector paths with fewer segments or less severe bend-points. +//! +//! You can set a function to be called when the connector has been rerouted +//! and needs to be redrawn. Alternatively, you can query the connector's +//! needsRepaint() function to determine this manually. +//! +//! Usually, it is expected that you would create a ConnRef for each connector +//! in your diagram and keep that reference in your own connector class. +//! class ConnRef { public: - ConnRef(Router *router, const unsigned int id); - ConnRef(Router *router, const unsigned int id, - const Point& src, const Point& dst); - virtual ~ConnRef(); + //! @brief Constructs a connector with no endpoints specified. + //! + //! @param[in] router The router scene to place the connector into. + //! @param[in] id A unique positive integer ID for the connector. + //! + //! If an ID is not specified, then one will be assigned to the shape. + //! If assigning an ID yourself, note that it should be a unique + //! positive integer. Also, IDs are given to all objects in a scene, + //! so the same ID cannot be given to a shape and a connector for + //! example. + //! + ConnRef(Router *router, const unsigned int id = 0); + //! @brief Constructs a connector with endpoints specified. + //! + //! @param[in] router The router scene to place the connector into. + //! @param[in] id A unique positive integer ID for the connector. + //! @param[in] src The source endpoint of the connector. + //! @param[in] dst The destination endpoint of the connector. + //! + //! If an ID is not specified, then one will be assigned to the shape. + //! If assigning an ID yourself, note that it should be a unique + //! positive integer. Also, IDs are given to all objects in a scene, + //! so the same ID cannot be given to a shape and a connector for + //! example. + //! + ConnRef(Router *router, const ConnEnd& src, const ConnEnd& dst, + const unsigned int id = 0); + //! @brief Destuctor. + ~ConnRef(); - void setType(unsigned int type); - PolyLine& route(void); - bool needsReroute(void); - void freeRoute(void); + //! @brief Sets both new source and destination endpoints for this + //! connector. + //! + //! @param[in] srcPoint New source endpoint for the connector. + //! @param[in] dstPoint New destination endpoint for the connector. + void setEndpoints(const ConnEnd& srcPoint, const ConnEnd& dstPoint); + //! @brief Sets just a new source endpoint for this connector. + //! + //! @param[in] srcPoint New source endpoint for the connector. + void setSourceEndpoint(const ConnEnd& srcPoint); + //! @brief Sets just a new destination endpoint for this connector. + //! + //! @param[in] dstPoint New destination endpoint for the connector. + void setDestEndpoint(const ConnEnd& dstPoint); + //! @brief Returns the ID of this connector. + //! @returns The ID of the connector. + unsigned int id(void) const; + //! @brief Returns a pointer to the router scene this connector is in. + //! @returns A pointer to the router scene for this connector. + Router *router(void) const; + + //! @brief Returns an indication of whether this connector has a + //! new route and thus needs to be repainted. + //! + //! If the connector has been rerouted and need repainting, the + //! route() method can be called to get a reference to the new route. + //! + //! @returns Returns true if the connector requires repainting, or + //! false if it does not. + bool needsRepaint(void) const; + + //! @brief Returns a reference to the current route for the connector. + //! + //! This is a "raw" version of the route, where each line segment in + //! the route may be made up of multiple collinear line segments. It + //! will also not have post-processing (like curved corners) applied + //! to it. The simplified route for display can be obtained by calling + //! displayRoute(). + //! + //! @returns The PolyLine route for the connector. + //! @note You can obtain a modified version of this poly-line + //! route with curved corners added by calling + //! PolyLine::curvedPolyline(). + const PolyLine& route(void) const; + + //! @brief Returns a reference to the current display version of the + //! route for the connector. + //! + //! The display version of a route has been simplified to collapse all + //! collinear line segments into single segments. It may also have + //! post-processing applied to the route, such as curved corners or + //! nudging. + //! + //! @returns The PolyLine display route for the connector. + PolyLine& displayRoute(void); + + //! @brief Sets a callback function that will called to indicate that + //! the connector needs rerouting. + //! + //! The cb function will be called when shapes are added to, removed + //! from or moved about on the page. The pointer ptr will be passed + //! as an argument to the callback function. + //! + //! @param[in] cb A pointer to the callback function. + //! @param[in] ptr A generic pointer that will be passed to the + //! callback function. + void setCallback(void (*cb)(void *), void *ptr); + //! @brief Returns the type of routing performed for this connector. + //! @return The type of routing performed. + //! + ConnType routingType(void) const; + //! @brief Sets the type of routing to be performed for this + //! connector. + //! + //! If a call to this method changes the current type of routing + //! being used for the connector, then it will get rerouted during + //! the next processTransaction() call, or immediately if + //! transactions are not being used. + //! + //! @param type The type of routing to be performed. + //! + void setRoutingType(ConnType type); + + + + // @brief Returns the source endpoint vertex in the visibility graph. + // @returns The source endpoint vertex. + VertInf *src(void); + // @brief Returns the destination endpoint vertex in the + // visibility graph. + // @returns The destination endpoint vertex. + VertInf *dst(void); + + + void set_route(const PolyLine& route); void calcRouteDist(void); - void updateEndPoint(const unsigned int type, const Point& point); void setEndPointId(const unsigned int type, const unsigned int id); unsigned int getSrcShapeId(void); unsigned int getDstShapeId(void); void makeActive(void); void makeInactive(void); - void lateSetup(const Point& src, const Point& dst); - unsigned int id(void); - VertInf *src(void); - VertInf *dst(void); + VertInf *start(void); void removeFromGraph(void); bool isInitialised(void); - void unInitialise(void); - void setCallback(void (*cb)(void *), void *ptr); - void handleInvalid(void); - int generatePath(Point p0, Point p1); void makePathInvalid(void); - Router *router(void); void setHateCrossings(bool value); bool doesHateCrossings(void); - - friend void Router::attachedShapes(IntList &shapes, - const unsigned int shapeId, const unsigned int type); - friend void Router::attachedConns(IntList &conns, - const unsigned int shapeId, const unsigned int type); - friend void Router::markConnectors(ShapeRef *shape); - + void setEndpoint(const unsigned int type, const ConnEnd& connEnd); + bool setEndpoint(const unsigned int type, const VertID& pointID, + Point *pointSuggestion = NULL); + private: + friend class Router; + + PolyLine& routeRef(void); + void freeRoutes(void); + void performCallback(void); + bool generatePath(void); + bool generatePath(Point p0, Point p1); + void unInitialise(void); + void updateEndPoint(const unsigned int type, const ConnEnd& connEnd); + void common_updateEndPoint(const unsigned int type, const ConnEnd& connEnd); Router *_router; unsigned int _id; - unsigned int _type; + ConnType _type; unsigned int _srcId, _dstId; + bool _orthogonal; bool _needs_reroute_flag; bool _false_path; + bool _needs_repaint; bool _active; PolyLine _route; + Polygon _display_route; double _route_dist; ConnRefList::iterator _pos; VertInf *_srcVert; VertInf *_dstVert; + VertInf *_startVert; bool _initialised; void (*_callback)(void *); void *_connector; @@ -96,6 +339,69 @@ class ConnRef }; +class PointRep; +typedef std::set PointRepSet; +typedef std::list PointRepList; + +class PointRep +{ + public: + PointRep(Point *p, const ConnRef *c) + : point(p), + conn(c) + + { + } + bool follow_inner(PointRep *target); + + Point *point; + const ConnRef *conn; + // inner_set: Set of pointers to the PointReps 'inner' of + // this one, at this corner. + PointRepSet inner_set; +}; + + +typedef std::pair PtConnPtrPair; + +class PtOrder +{ + public: + PtOrder() + { + } + ~PtOrder(); + bool addPoints(const int dim, PtConnPtrPair innerArg, + PtConnPtrPair outerArg, bool swapped); + void sort(const int dim); + int positionFor(const ConnRef *conn, const size_t dim) const; + + // One for each dimension. + PointRepList connList[2]; +}; + +typedef std::map PtOrderMap; +typedef std::set PointSet; + + +const unsigned int CROSSING_NONE = 0; +const unsigned int CROSSING_TOUCHES = 1; +const unsigned int CROSSING_SHARES_PATH = 2; +const unsigned int CROSSING_SHARES_PATH_AT_END = 4; +const unsigned int CROSSING_SHARES_FIXED_SEGMENT = 8; + + +typedef std::pair CrossingsInfoPair; + +extern CrossingsInfoPair countRealCrossings( Avoid::Polygon& poly, + bool polyIsConn, Avoid::Polygon& conn, size_t cIndex, + bool checkForBranchingSegments, const bool finalSegment = false, + PointSet *crossingPoints = NULL, PtOrderMap *pointOrders = NULL, + ConnRef *polyConnRef = NULL, ConnRef *connConnRef = NULL); +extern void splitBranchingSegments(Avoid::Polygon& poly, bool polyIsConn, + Avoid::Polygon& conn, const double tolerance = 0); +extern bool validateBendPoint(VertInf *aInf, VertInf *bInf, VertInf *cInf); + }