Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
rtree-toy.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2009 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it either under the terms of the GNU Lesser General Public
6 * License version 2.1 as published by the Free Software Foundation
7 * (the "LGPL") or, at your option, under the terms of the Mozilla
8 * Public License Version 1.1 (the "MPL"). If you do not alter this
9 * notice, a recipient may use your version of this file under either
10 * the MPL or the LGPL.
11 *
12 * You should have received a copy of the LGPL along with this library
13 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 * You should have received a copy of the MPL along with this library
16 * in the file COPYING-MPL-1.1
17 *
18 * The contents of this file are subject to the Mozilla Public License
19 * Version 1.1 (the "License"); you may not use this file except in
20 * compliance with the License. You may obtain a copy of the License at
21 * http://www.mozilla.org/MPL/
22 *
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
24 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
25 * the specific language governing rights and limitations.
26 */
27
28/*
29 initial toy for redblack trees
30*/
31
32
33#include <toys/path-cairo.h>
35
36#include <time.h>
37#include <vector>
38#include <sstream>
39#include <getopt.h>
40
42#include "../2geom/orphan-code/rtree.cpp"
43
44
45//using std::vector;
46using namespace Geom;
47using namespace std;
48
49// make sure that in RTreeToy() constructor you assign the same number of colors
50// otherwise, they extra will be black :P
51const int no_of_colors = 8;
52const string search_str = "Mode: Search (Area: Click whitespace and Drag)";
53const string update_str = "Mode: Update (Click Bounding Box (dark gray) and Drag) NOT implemented";
54const string insert_str = "Mode: Insert (Click whitespace and Drag)" ;
55const string erase_str = "Mode: Delete (Click on Bounding Box (dark gray))";
56const string help_str = "'I': Insert, 'U': Update, 'S': Search, 'D': Delete";
57
58
59const char* program_name;
60
61class RTreeToy: public Toy
62{
63
64// PointSetHandle handle_set;
65// std::vector< Handle > rectangle_handles;
66 std::vector< RectHandle > rectangles;
67
68 Geom::Point starting_point; // during click and drag: start point of click
69 Geom::Point ending_point; // during click and drag: end point of click (release)
70 Geom::Point highlight_point; // not used
71
72 // colors we are going to use for different purposes
73 colour color_shape, color_shape_guide;
74 colour color_select_area, color_select_area_guide; // red(a=0.6), red
75
76 bool add_new_rect;
77 bool delete_rect;
78
79 Rect rect_chosen; // the rectangle of the search area
80 Rect dummy_draw; // the "helper" rectangle that is shown during the click and drag (before the mouse release)
81
82 // save the bounding boxes of the tree in here
83 std::vector< std::vector< Rect > > rects_level;
84 std::vector<colour> color_rtree_level;
85 unsigned drawBB_color;
86 bool drawBB_color_all;
87
88 enum the_modes {
89 INSERT_MODE = 0,
90 UPDATE_MODE,
91 DELETE_MODE,
92 SEARCH_MODE,
93 } mode; // insert/alter, search, delete modes
94 bool drawBB; // draw bounding boxes of RTree
95 string out_str, drawBB_str, drawBB_color_str;
96
97 // printing of the tree
98 //int help_counter; // the "x" of the label of each node
99 static const int label_size = 15 ; // size the label of each node
100
101 Geom::RTree rtree;
102
103 void * hit;
104 unsigned rect_id;
105
106
107 // used for the keys that switch between modes
108 enum menu_item_t
109 {
110 INSERT_I = 0,
111 UPDATE_U,
112 DELETE_D,
113 SEARCH_S,
114 BB_TOGGLE_T,
115 BB_DRAW_0,
116 BB_DRAW_1,
117 BB_DRAW_2,
118 BB_DRAW_3,
119 BB_DRAW_4,
120 BB_DRAW_5,
121 BB_DRAW_ALL_O,
122 TOTAL_ITEMS // this one must be the last item
123 };
124 static const char* menu_items[TOTAL_ITEMS];
125 static const char keys[TOTAL_ITEMS];
126
127
128
129 void draw( cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream ) override {
130 cairo_set_line_width( cr, 1 );
131 cairo_set_source_rgba( cr, color_shape );
132 cairo_stroke( cr );
133
134 // draw the shapes we save in the rtree
135 for(auto & rectangle : rectangles){
136 rectangle.draw( cr, true );
137 }
138 cairo_set_source_rgba( cr, color_shape );
139 cairo_stroke( cr );
140
141 // draw a rect if we did click & drag (so that we know what we are going to create)
142 if( add_new_rect ){
143 dummy_draw = Rect( starting_point, ending_point );
144 cairo_rectangle( cr, dummy_draw );
145 if( mode == INSERT_MODE ){
146 cairo_set_source_rgba( cr, color_shape_guide );
147 }
148 else if( mode == SEARCH_MODE ){
149 cairo_set_source_rgba( cr, color_select_area_guide );
150 }
151 cairo_stroke( cr );
152 }
153
154 // draw a rect for the search area
155 cairo_rectangle( cr, rect_chosen );
156 cairo_set_source_rgba( cr, color_select_area );
157 cairo_stroke( cr );
158
159 *notify << help_str << "\n"
160 << "'T': Bounding Boxes: " << drawBB_str << ", '0'-'" << no_of_colors << "', 'P': Show Layer: " << drawBB_color_str << "\n"
161 << out_str;
162
163 if( drawBB ){
164 for(unsigned color = 0 ; color < rects_level.size() ; color++ ){
165 if( drawBB_color == color || drawBB_color_all ){
166 for(auto & j : rects_level){
167 cairo_rectangle( cr, j );
168 }
169 cairo_set_source_rgba( cr, color_rtree_level[color] );
170 cairo_stroke( cr );
171 }
172 }
173 }
174
175 Toy::draw( cr, notify, width, height, save,timer_stream );
176 }
177
178 void mouse_moved( GdkEventMotion* e ) override{
179 if(add_new_rect &&
180 ( mode == INSERT_MODE || mode == SEARCH_MODE ) )
181 {
182 Toy::mouse_moved( e );
183 ending_point = Point( e->x, e->y );
184 }
185 }
186
187 void mouse_pressed( GdkEventButton* e ) override {
189 if(e->button == 1){ // left mouse button
190 if( mode == INSERT_MODE ){
191 starting_point = Point( e->x, e->y );
192 ending_point = starting_point;
193 add_new_rect = true;
194 }
195 else if( mode == SEARCH_MODE ){
196 starting_point = Point( e->x, e->y );
197 ending_point = starting_point;
198 add_new_rect = true;
199 }
200 else if( mode == DELETE_MODE ) {
201 Geom::Point mouse(e->x, e->y);
202 unsigned i = 0;
203 for( i = 0; i < rectangles.size(); i++) {
204 hit = rectangles[i].hit(mouse);
205 if( hit ) {
206 break;
207 }
208 }
209 if( hit ){
210 // erase specific element
211 stringstream shape_id( rectangles[i].name );
212 unsigned shape_id_int;
213 shape_id >> shape_id_int;
214
215 rtree.erase( rectangles[i].pos, shape_id_int );
216 rectangles.erase( rectangles.begin() + i );
217// check_if_deleted( );
218// check_if_duplicates( );
219 delete_rect = true;
220 }
221 hit = NULL;
222 }
223 }
224 else if( e->button == 2 ){ //middle button
225 }
226 else if( e->button == 3 ){ //right button
227 }
228 }
229
230 void mouse_released( GdkEventButton* e ) override {
232 if( e->button == 1 ) { //left mouse button
233 if( mode == INSERT_MODE ) {
234 if( add_new_rect ){
235 ending_point = Point( e->x, e->y );
236 RectHandle t( Rect(starting_point, ending_point), false );
237
238 std::stringstream out;
239 out << rect_id;;
240 t.name = out.str();
241 rectangles.push_back( t );
242 rect_id++;
243
244 insert_in_tree_the_last_rect();
245 find_rtree_subtrees_bounding_boxes( rtree );
246 add_new_rect = false;
247 }
248 }
249 else if( mode == SEARCH_MODE ){
250 if( add_new_rect ){
251 ending_point = Point( e->x, e->y );
252 rect_chosen = Rect( starting_point, ending_point );
253
254 std::vector< int > result(0);
255
256 if( rtree.root ){
257 rtree.search( rect_chosen, &result, rtree.root );
258 }
259 std::cout << "Search results: " << result.size() << std::endl;
260 for(int i : result){
261 std::cout << i << ", " ;
262 }
263 std::cout << std::endl;
264
265 add_new_rect = false;
266 }
267 }
268 else if( mode == DELETE_MODE ) { // mode: delete
269 if( delete_rect ){
270 delete_rect = false;
271 if( rtree.root ){
272 find_rtree_subtrees_bounding_boxes( rtree );
273 }
274 std::cout << " \nTree:\n" << std::endl;
275 rtree.print_tree( rtree.root, 0 );
276 std::cout << "...done\n" << std::endl;
277 }
278 }
279 }
280 else if( e->button == 2 ){ //middle button
281 }
282 else if( e->button == 3 ){ //right button
283 }
284 }
285
286
287 void key_hit( GdkEventKey *e ) override
288 {
289 char choice = std::toupper( keyval );
290 switch ( choice )
291 {
292 case 'I':
293 mode = INSERT_MODE;
294 out_str = insert_str;
295 break;
296 case 'S':
297 mode = SEARCH_MODE;
298 out_str = search_str;
299 break;
300 case 'D':
301 mode = DELETE_MODE;
302 out_str = erase_str;
303 break;
304 case 'U':
305 mode = UPDATE_MODE;
306 out_str = update_str;
307 break;
308 case 'T':
309 if( drawBB ){
310 drawBB = false;
311 drawBB_str = "OFF";
312 }
313 else{
314 drawBB = true;
315 drawBB_str = "ON";
316 }
317 break;
318 case 'P':
319 drawBB_color_all = true;
320 drawBB_color = 9;
321 drawBB_color_str = "all";
322 break;
323 case '0':
324 drawBB_color_all = false;
325 drawBB_color = 0;
326 drawBB_color_str = "0";
327 break;
328 case '1':
329 drawBB_color_all = false;
330 drawBB_color = 1;
331 drawBB_color_str = "1";
332 break;
333 case '2':
334 drawBB_color_all = false;
335 drawBB_color = 2;
336 drawBB_color_str = "2";
337 break;
338 case '3':
339 drawBB_color_all = false;
340 drawBB_color = 3;
341 drawBB_color_str = "3";
342 break;
343 case '4':
344 drawBB_color_all = false;
345 drawBB_color = 4;
346 drawBB_color_str = "4";
347 break;
348 case '5':
349 drawBB_color_all = false;
350 drawBB_color = 5;
351 drawBB_color_str = "5";
352 break;
353 case '6':
354 drawBB_color_all = false;
355 drawBB_color = 6;
356 drawBB_color_str = "6";
357 break;
358 case '7':
359 drawBB_color_all = false;
360 drawBB_color = 7;
361 drawBB_color_str = "7";
362 break;
363 }
364 redraw();
365 }
366
367
368 void insert_in_tree_the_last_rect(){
369 unsigned i = rectangles.size() - 1;
370 Rect r1 = rectangles[i].pos;
371
372 stringstream shape_id( rectangles[i].name );
373 unsigned shape_id_int;
374 shape_id >> shape_id_int;
375
376 // insert in R tree
377 rtree.insert( r1, shape_id_int );
378 std::cout << " \nTree:\n" << std::endl;
379 rtree.print_tree( rtree.root, 0 );
380 std::cout << "...done\n" << std::endl;
381 };
382
383
384 void find_rtree_subtrees_bounding_boxes( Geom::RTree tree ){
385 if( tree.root ){
386 // clear existing bounding boxes
387 for(auto & color : rects_level){
388 color.clear();
389 }
390 save_bb( tree.root, 0);
391 }
392 };
393
394 // TODO fix this.
395 void save_bb( Geom::RTreeNode* subtree_root, int depth )
396 {
397 if( subtree_root->children_nodes.size() > 0 ){
398
399 // descend in each one of the elements and call print_tree
400 for(auto & children_node : subtree_root->children_nodes){
401 Rect r1( children_node.bounding_box );
402 rects_level[ depth ].push_back( r1 );
403
404 if( depth == no_of_colors - 1 ){ // if we reached Nth levels of colors, roll back to color 0
405 save_bb( children_node.data, 0);
406 }
407 else{
408 save_bb( children_node.data, depth+1);
409 }
410 }
411 }
412 // else do nothing, entries are the rects themselves...
413 };
414
415
416
417public:
418 RTreeToy(unsigned rmin, unsigned rmax, char /*handlefile*/):
419 rectangles(0),
420 color_shape(0, 0, 0, 0.9), color_shape_guide(1, 0, 0, 1),
421 color_select_area(1, 0, 0, 0.6 ), color_select_area_guide(1, 0, 0, 1 ), //1, 0, 0, 1
422 add_new_rect( false ), delete_rect( false ),
423 rect_chosen(), dummy_draw(),
424 rects_level( no_of_colors ),
425 color_rtree_level( no_of_colors, colour(0, 0, 0, 0) ),
426 drawBB_color(9), drawBB_color_all(true),
427 mode( INSERT_MODE ), drawBB(true),
428 out_str( insert_str ),
429 drawBB_str("ON"), drawBB_color_str("all"),
430 rtree( rmin, rmax, QUADRATIC_SPIT ),
431 hit( 0 ), rect_id( 0 )
432 {
433 // only "bright" colors
434 color_rtree_level[0] = colour(0, 0.80, 1, 1); // cyan
435 color_rtree_level[1] = colour(0, 0.85, 0, 1); // green
436 color_rtree_level[2] = colour(0.75, 0, 0.75, 1); // purple
437 color_rtree_level[3] = colour(0, 0, 1, 1); // blue
438 color_rtree_level[4] = colour(1, 0.62, 0, 1); // orange
439 color_rtree_level[5] = colour(1, 0, 0.8, 1); // pink
440 color_rtree_level[6] = colour(0.47, 0.26, 0.12, 1);
441 color_rtree_level[7] = colour(1, 0.90, 0, 1); // yellow
442 }
443
444};
445
446
447
448int main(int argc, char **argv) {
449
450 char* min_arg = NULL;
451 char* max_arg = NULL;
452
453 int set_min_max = 0;
454
455 int c;
456
457 while (1)
458 {
459 static struct option long_options[] =
460 {
461 /* These options set a flag. */
462 /* These options don't set a flag.
463 We distinguish them by their indices. */
464 {"min-nodes", required_argument, 0, 'n'},
465 {"max-nodes", required_argument, 0, 'm'},
466 {"help", no_argument, 0, 'h'},
467 {0, 0, 0, 0}
468 };
469 /* getopt_long stores the option index here. */
470 int option_index = 0;
471
472 c = getopt_long (argc, argv, "n:m:h",
473 long_options, &option_index);
474
475 /* Detect the end of the options. */
476 if (c == -1){
477 break;
478 }
479
480 switch (c)
481 {
482 case 'n':
483 min_arg = optarg;
484 set_min_max += 1;
485 break;
486
487
488 case 'm':
489 max_arg = optarg;
490 set_min_max += 2;
491 break;
492
493
494 case 'h':
495 std::cerr << "Usage: " << argv[0] << " options\n" << std::endl ;
496 std::cerr <<
497 " -n --min-nodes=NUMBER minimum number in node.\n" <<
498 " -m --max-nodes=NUMBER maximum number in node.\n" <<
499 " -h --help Print this help.\n" << std::endl;
500 exit(1);
501 break;
502
503
504 case '?':
505 /* getopt_long already printed an error message. */
506 break;
507
508 default:
509 abort ();
510 }
511 }
512
513 unsigned rmin = 0;
514 unsigned rmax = 0;
515
516 if( set_min_max == 3 ){
517 stringstream s1( min_arg );
518 s1 >> rmin;
519
520 stringstream s2( max_arg );
521 s2 >> rmax;
522 if( rmax <= rmin || rmax < 2 || rmin < 1 ){
523 std::cerr << "Rtree set to 2, 3" << std::endl ;
524 rmin = 2;
525 rmax = 3;
526 }
527 }
528 else{
529 std::cerr << "Rtree set to 2, 3 ." << std::endl ;
530 rmin = 2;
531 rmax = 3;
532 }
533
534
535 char handlefile = 'T';
536 std::cout << "rmin: " << rmin << " rmax:" << rmax << std::endl;
537 init(argc, argv, new RTreeToy( rmin, rmax, handlefile) );
538
539 return 0;
540}
541
542
543
544const char* RTreeToy::menu_items[] =
545{
546 "Insert / Alter Rectangle",
547 "Search Rectangle",
548 "Delete Reactangle",
549 "Toggle"
550};
551
552const char RTreeToy::keys[] =
553{
554 'I', 'U', 'S', 'D', 'T',
555 '0', '1', '2', '3', '4', '5', 'P'
556};
557
558
559
560
561
562
563/*
564intersection test
565 Rect r1( Point(100, 100), Point(150, 150)),
566 r2( Point(200, 200), Point(250, 250)),
567 r3( Point(50, 50), Point(100, 100));
568 OptRect a_intersection_b;
569 a_intersection_b = intersect( r1, r2 );
570 std::cout << "r1, r2 " << a_intersection_b.empty() << std::endl;
571 a_intersection_b = intersect( r1, r3 );
572 std::cout << "r1, r3 " << a_intersection_b.empty() << std::endl;
573*/
SimpleSnap option
int main()
Two-dimensional point that doubles as a vector.
Definition point.h:66
std::vector< RTreeRecord_NonLeaf > children_nodes
Definition rtree.h:144
RTreeNode * root
Definition rtree.h:154
int erase(const Rect &search_area, const int shape_to_delete)
Definition rtree.cpp:1014
void insert(Rect const &r, unsigned shape)
Definition rtree.cpp:69
void print_tree(RTreeNode *subtree_root, int depth) const
Definition rtree.cpp:878
void search(const Rect &search_area, std::vector< int > *result, const RTreeNode *subtree) const
Definition rtree.cpp:974
Axis aligned, non-empty rectangle.
Definition rect.h:92
std::string name
virtual void mouse_pressed(Geom::Point const &pos, unsigned button, unsigned modifiers)
virtual void mouse_moved(Geom::Point const &pos, unsigned modifiers)
virtual void mouse_released(Geom::Point const &pos, unsigned button, unsigned modifiers)
virtual void save(FILE *f)
std::string name
virtual void key_hit(unsigned keyval, unsigned modifiers)
virtual void draw(cairo_t *cr, std::ostringstream *notify, int w, int h, bool save, std::ostringstream *timing_stream)
Css & result
double c[8][4]
Various utility functions.
Definition affine.h:22
@ QUADRATIC_SPIT
Definition rtree.h:61
STL namespace.
int mode
void cairo_rectangle(cairo_t *cr, Geom::Rect const &r)
struct _cairo cairo_t
Definition path-cairo.h:16
SpatialIndex::ISpatialIndex * tree
const string search_str
Definition rtree-toy.cpp:52
const int no_of_colors
Definition rtree-toy.cpp:51
const string erase_str
Definition rtree-toy.cpp:55
const string insert_str
Definition rtree-toy.cpp:54
const string update_str
Definition rtree-toy.cpp:53
const string help_str
Definition rtree-toy.cpp:56
const char * program_name
Definition rtree-toy.cpp:59
Implementation of Red-Black Tree as described in Intorduction to Algorithms.
double height
double width
void cairo_set_source_rgba(cairo_t *cr, colour c)
void redraw()
void init(int argc, char **argv, Toy *t, int width=600, int height=600)