Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
convex_hull.cpp
Go to the documentation of this file.
1/*
2 * vim: ts=4 sw=4 et tw=0 wm=0
3 *
4 * libcola - A library providing force-directed network layout using the
5 * stress-majorization method subject to separation constraints.
6 *
7 * Copyright (C) 2006-2008 Monash University
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library in the file LICENSE; if not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307 USA
23 *
24*/
25
30#include <valarray>
31#include <algorithm>
32#include <libcola/convex_hull.h>
33#include "graphlayouttest.h"
34
35#include <string>
36#include <iostream>
37#include <cairomm/context.h>
38#include <cairomm/surface.h>
39
40/* M_PI is defined in math.h in the case of Microsoft Visual C++ */
41#if defined(_MSC_VER)
42#define _USE_MATH_DEFINES
43#include <math.h>
44#endif
45using namespace std;
46
47typedef vector<unsigned> Hull;
51void randTest(unsigned n, valarray<double>& X, valarray<double>& Y) {
52 X.resize(n);
53 Y.resize(n);
54 srand(time(nullptr));
55 for(unsigned i=0;i<n;i++) {
56 X[i]=getRand(1.);
57 Y[i]=getRand(1.);
58 }
59}
66void tworects(valarray<double>& X, valarray<double>& Y, Hull& expectedHull) {
67 const unsigned n=8;
68 X.resize(n);
69 Y.resize(n);
70 X[0]=330.011898, Y[0]=203.250425;
71 X[1]=330.011898, Y[1]=237.250425;
72 X[2]=276.011898, Y[2]=237.250425;
73 X[3]=276.011898, Y[3]=203.250425;
74 X[4]=459.998300, Y[4]=203.250425;
75 X[5]=459.998300, Y[5]=237.250425;
76 X[6]=405.998300, Y[6]=237.250425;
77 X[7]=405.998300, Y[7]=203.250425;
78 unsigned hull[]={3,4,5,2};
79 unsigned m=sizeof(hull)/sizeof(unsigned);
80 expectedHull.resize(m);
81 copy(hull,hull+m,expectedHull.begin());
82}
83
84int drawCairo(const string& fname,
85 const valarray<double>& X, const valarray<double>& Y,
86 const Hull& hull);
87
88int main(int argc, char** argv) {
89 valarray<double> X, Y;
90 Hull h,expectedHull;
91 tworects(X,Y,expectedHull);
92 hull::convex(X,Y,h);
93 printf("hull size=%d\n",h.size());
94 pair<Hull::iterator,Hull::iterator> r
95 =mismatch(h.begin(),h.end(),expectedHull.begin());
96 assert(r.first==h.end());
97 drawCairo("convex_tworects.svg",X,Y,h);
98
99 randTest(20,X,Y);
100 hull::convex(X,Y,h);
101 drawCairo("convex_hull_random.svg",X,Y,h);
102 return 0;
103}
104
105/***********CAIRO CODE***************************************************/
106double width = 600;
107double height = 400;
108double border=10;
109void dot(Cairo::RefPtr<Cairo::Context> & cr, double x, double y) {
110 cr->arc(x, y,
111 2., 0.0, 2.0 * M_PI);
112 cr->stroke();
113}
114
115double xcoord(double x) {
116 return border+x*width;
117}
118double ycoord(double y) {
119 return border+y*height;
120}
121int drawCairo(const string& fname,
122 const valarray<double>& Xin, const valarray<double>& Yin,
123 const Hull& hull) {
124#ifdef CAIRO_HAS_SVG_SURFACE
125 unsigned n=Xin.size();
126 assert(Yin.size()==n);
127
128 // normalise coords to range 0-1
129 valarray<double> X=Xin, Y=Yin;
130 X-=X.min();
131 Y-=Y.min();
132 X/=X.max();
133 Y/=Y.max();
134
135 Cairo::RefPtr<Cairo::SvgSurface> surface =
136 Cairo::SvgSurface::create(fname, width+2*border, height+2*border);
137
138 Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(surface);
139
140 cr->save(); // save the state of the context
141 cr->set_source_rgba(0.0, 0.0, 0.0, 0.7);
142 // draw a circle at each coordinate
143 for(unsigned i=0;i<n;i++) {
144 dot(cr,xcoord(X[i]),ycoord(Y[i]));
145 }
146
147 cr->set_source_rgba(0.0, 0.0, 0.0, 0.3);
148 cr->move_to(xcoord(X[hull[0]]),ycoord(Y[hull[0]]));
149 for(unsigned i=1;i<hull.size();i++) {
150 cr->line_to(xcoord(X[hull[i]]),ycoord(Y[hull[i]]));
151 }
152 cr->line_to(xcoord(X[hull[0]]),ycoord(Y[hull[0]]));
153 cr->stroke();
154 cr->set_source_rgba(0.0, 0.0, 0.0, 1.);
155 for(vector<unsigned>::const_iterator i=hull.begin();i!=hull.end();++i) {
156 unsigned j=*i;
157 stringstream ss;
158 ss<<j;
159 printf("p[%d]=(%f,%f)\n",j,X[j],Y[j]);
160 cr->move_to(xcoord(X[j]),ycoord(Y[j]));
161 cr->show_text(ss.str());
162 cr->stroke();
163 }
164 cr->restore();
165
166 cr->show_page();
167
168 cout << "Wrote SVG file \"" << fname << "\"" << endl;
169 return 0;
170
171#else
172
173 cout << "You must compile cairo with SVG support for this example to work."
174 << endl;
175 return 1;
176
177#endif
178
179}
180// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 :
int main()
Cairo::RefPtr< Cairo::ImageSurface > surface
Definition canvas.cpp:137
double getRand(double range)
void convex(const unsigned n, const double *X, const double *Y, vector< unsigned > &h)
STL namespace.
double xcoord(double x)
double border
vector< unsigned > Hull
void dot(Cairo::RefPtr< Cairo::Context > &cr, double x, double y)
void randTest(unsigned n, valarray< double > &X, valarray< double > &Y)
generates a random set of n points in X and Y.
double height
double ycoord(double y)
double width
int drawCairo(const string &fname, const valarray< double > &X, const valarray< double > &Y, const Hull &hull)
void tworects(valarray< double > &X, valarray< double > &Y, Hull &expectedHull)
generates a set of 8 points (actually the vertices of two rectangles) which lineup horizontally.