summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/adaptagrams/libavoid/doc/example.doc
blob: a23933d22069045943fcffc6782feed0f2992e0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*!

@page libavoid_example libavoid — Documented code example

libavoid is a C++ library.  Its code is all within the Avoid namespace.

First, you must create an instance of the router. 
@code
Avoid::Router *router = new Avoid::Router(Avoid::PolyLineRouting); @endcode

To add a shape (obstacle) to the router, you first create a Avoid::ShapeRef by giving the bounding box of the obstacle.  This adds the shape to the router (and cause rerouting of connectors it intersects).  It also passes ownership of the shapeRef object to the router instance, though it is still fine for you to keep a reference to it.
@code
// Create the ShapeRef:
Avoid::Rectangle rectangle(Avoid::Point(20.0, 35.0), Avoid::Point(40.0, 12.0));
Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, rectangle); @endcode
or
@code 
Avoid::Polygon shapePoly(3);
shapePoly.ps[0] = Avoid::Point(1.0, 1.0);
shapePoly.ps[1] = Avoid::Point(2.5, 1.5);
shapePoly.ps[2] = Avoid::Point(1.5, 2.5);
Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly); @endcode

The relevant prototypes (all in the Avoid namespace) are as follows.  If a shape ID is specified, it should be non-zero and unique among all shapes and connectors.
@code
Avoid::Rectangle(const Avoid::Point& topLeft, const Avoid::Point& bottomRight);
Avoid::Rectangle(const Avoid::Point& centre, const double width, const double height);
Avoid::ShapeRef(Avoid::Router *router, const Avoid::Polygon& polygon, unsigned int id = 0); @endcode


To move or resize a shape already in the router, you do the following:
@code
router->moveShape(shapeRef, newPolygon); @endcode
or
@code
double xmove = 20, ymove = 15;
router->moveShape(shapeRef, xmove, ymove); @endcode

In its default mode the router will queue multiple shape movements and perform the changes to the visibility graph in an optimised order.  Thus you make several calls to Avoid::Router::moveShape() for different shapes and then tell the router to process the moves.  This tend to be useful in interactive applications where the user may move multiple shapes at once.
@code
router->moveShape(shapeRef1, newPolygon1);
router->moveShape(shapeRef2, newPolygon2);
router->processTransaction();
 @endcode

To delete a shape from the router (and reroute connectors that then have a better path) you do the following.  
@code
router->deleteShape(shapeRef); @endcode
This will cause the router to free the memory for the shapeRef.  You should discard your reference to the shapeRef after this call.

To add a new connector to the router, you do the following:
@code 
Avoid::ConnEnd srcPt(Avoid::Point(1.2, 0.5));
Avoid::ConnEnd dstPt(Avoid::Point(3.0, 4.0));
Avoid::ConnRef *connRef = new Avoid::ConnRef(router, srcPt, dstPt); @endcode
This passes ownership of the connRef object to the router instance, though it is still fine for you to keep a reference to it.

To remove a connector from the router:
@code
router->deleteConnector(connRef); @endcode
This will cause the router to free the memory for the connRef.  You should discard your reference to the connRef after this call.

You can set a function to be called when the connector needs to be redrawn.  When called, this function will be passed the pointer given as a second argument to Avoid::ConnRef::setCallback():
@code
void connCallback(void *ptr)
{
    Avoid::ConnRef *connRef = (Avoid::ConnRef *) ptr;
    printf("Connector %u needs rerouting!\n", connRef->id());
}
connRef->setCallback(connCallback, connRef); @endcode

The callback will be triggered by movement, addition and deletion of shapes, as well as by adjustment of the connector endpoints, or by processing a transaction that includes any of these events.  You can check if a connector path has changed, and hence the object requires repainting (say because a better path is available due to a shape being deleted):
@code
if (connRef->needsRepaint()) ... @endcode

If you want to trigger the callback for a connector after moving its endpoints (or when it is first created you can do this via:
@code
connRef->processTransaction(); @endcode

You can then get the new path as follows:

@code
const Avoid::PolyLine route = connRef->dispayRoute();
for (size_t i = 0; i < route.size(); ++i) 
{
    Avoid::Point point = route.at(i);
    printf("%f, %f\n", point.x, point.y);
} @endcode       

Obviously the alternative to using the callback mechanism is to iterate through all connectors and check their needsRepaint() value after having called processTransaction().

You can update the endpoints of a connector with:
@code
Avoid::ConnEnd newSrcPt(Avoid::Point(6, 3));
Avoid::ConnEnd newDstPt(Avoid::Point(12, 67));
connRef->setEndpoints(newSrcPt, newDstPt); @endcode
or
@code
Avoid::ConnEnd newSrcPt(Avoid::Point(6, 3));
connRef->setSourceEndpoint(newSrcPt);

Avoid::ConnEnd newDstPt(Avoid::Point(6, 3));
connRef->setDestEndpoint(newDstPt); @endcode

You can also create connection pins on shapes and attach connectors directly to these.  Then when you move or resize the shapes, the connector endpoints attached to them will be automatically rerouted.

You can create a connection pin as follows:
@code
const unsigned int CENTRE = 1;
new Avoid::ShapeConnectionPin(shapeRef, CENTRE, Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE); @endcode
This one connects to the centre of the shape, but the position can be specified anywhere within the shape as a proportion of the shape's width and height.  

You can then attach a connector to the connection pin be doing the following:
@code
Avoid::ConnEnd newSrcPt(shapeRef, CENTRE);
connRef->setSourceEndpoint(newSrcPt); @endcode


See also a short example: example.cpp in the libavoid/tests directory

*/