home *** CD-ROM | disk | FTP | other *** search
- #include <LEDA/graph.h>
- #include <LEDA/d_array.h>
- #include <LEDA/plane.h>
- #include <LEDA/window.h>
-
- #include <math.h>
-
- declare2(GRAPH,point,int)
- declare(node_array,node)
- declare2(d_array,point,node)
- declare2(d_array,node,int)
-
- void GED(string);
-
- /*---------------------- globale Variablen --------------------------*/
-
- string G_filename;
-
- window W;
-
- double W_WIDTH = 100; // extension of gwindow W
-
- GRAPH(point,int) G; // graph G
-
- drawing_mode W_save_mode;
-
-
- int G_max_node_width = 15;
-
- double G_XMAX;
- double G_YMAX;
- double G_XMIN;
- double G_YMIN;
-
- int G_node_count; // counter of nodes,edges,faces
- int G_edge_count;
-
- d_array(node,int) G_node_name; // node -> name
-
- list(point) error_nodes; // error output
- list(segment) error_edges;
-
- bool output_enable = true; // output-permission
- bool still_saved = true; // save-control
-
-
- /*------------------------------ error --------------------------------*/
-
- void error(string text)
- {
- if (output_enable) cout << "\n(error) " << text << "\n";
- }
-
- /*------------------------------ warn --------------------------------*/
-
- void warn(string text)
- {
- cout << "(warning) " << text << "\n";
- }
-
- /*------------------------ draw_node_cursor ---------------------------*/
-
- static void draw_node_cursor(double x, double y)
- {
- W.draw_node(x,y);
- }
-
- /*---------------------------- draw_node ------------------------------*/
-
- void draw_node(node v,color c=black)
- {
- int width = W.get_node_width();
-
- if (width >= 7 ) W.draw_text_node(G[v],form("%d",G_node_name[v]),c);
- else W.draw_filled_node(G[v],c);
- }
-
- /*----------------------------- draw_edge -----------------------------*/
-
- void draw_edge(edge e,color c=black)
- {
- drawing_mode old_mode = W.set_mode(src_mode); // src_mode for edge-painting
-
- W.draw_edge_arrow(G[source(e)],G[target(e)],c);
-
- W.set_mode(old_mode);
-
- } // draw_edge
-
- /*--------------------------- redraw_graph ----------------------------*/
-
- void redraw_graph(string clear_permission)
- {
- node v;
- edge e;
-
- if (clear_permission == "yes") W.clear();
-
- forall_nodes(v,G) draw_node(v);
-
- forall_edges(e,G) draw_edge(e);
-
- } // redraw_graph
-
- void redraw_graph() { redraw_graph("yes"); }
-
- /*------------------------ new_error_node --------------------------*/
-
- void new_error_node(point p)
- {
- if (error_nodes.search(p)==nil) error_nodes.append(p);
-
- } // new_error_node
-
- /*------------------------ new_error_edge --------------------------*/
-
- void new_error_edge(segment s)
- {
- if (error_edges.search(s)==nil) error_edges.append(s);
-
- } // new_error_edge
-
- /*----------------------- overlap_message -------------------------*/
-
- void overlap_message(bool draw_permission = true)
- {
- point p;
- segment seg;
-
- line_style old_style = W.set_line_style(dotted);
- drawing_mode old_mode = W.set_mode(src_mode);
-
- forall(seg,error_edges) W.draw_edge_arrow(seg.start(),seg.end());
- forall(p,error_nodes) W.draw_filled_node(p);
-
- W.message(" node/edge dropped on existing object");
- W.message("");
- W.message(" < press button >");
- W.read_mouse();
- W.del_message();
-
- W.set_line_style(old_style); // old-values
- W.set_mode(old_mode);
-
- error_edges.clear();
- error_nodes.clear();
-
- if (draw_permission) redraw_graph();
-
- } // overlap_message
-
- /*---------------------------- cmp ---------------------------------*/
-
- int cmp(point& x,point& p, point& q)
- {
- segment s1(x,p); // compare relativ position of s1 & s2
- segment s2(x,q);
-
- return compare(s1.angle(), s2.angle());
-
- } // cmp
-
- /*---------------------- get_node_at_point ---------------------------*/
-
- node get_node_at_point(point pv)
- {
- node w,n;
- double dist = W.get_node_width() / W.scale();
-
- forall_nodes(w,G)
- {
- point pw = G[w];
-
- if (pv.distance(pw) < dist)
- {
- n = w;
- G.reset();
- return n; // node n on clicked position pv
- }
- }
-
- return nil; // no node clicked
-
- } // get_node_at_point
-
- /*------------------------ get_max_coord ----------------------------*/
-
- void get_max_coord()
- {
- node n = G.choose_node();
-
- if (n == nil)
- {
- G_XMAX = W.xmin(); G_YMAX = W.ymin(); // reset max.coord. of
- G_XMIN = W.xmax(); G_YMIN = W.ymax(); // empty graph G
- }
- else
- {
- point p = G[n];
-
- G_XMIN = G_XMAX = p.xcoord(); // set max.coord. of graph G
- G_YMIN = G_YMAX = p.ycoord(); // to existing node
- }
-
- forall_nodes(n,G)
- {
- real x = G[n].xcoord();
- real y = G[n].ycoord();
-
- if ( x < G_XMIN ) G_XMIN = x;
- if ( x > G_XMAX ) G_XMAX = x;
- if ( y < G_YMIN ) G_YMIN = y;
- if ( y > G_YMAX ) G_YMAX = y;
- }
-
- } // get_max_coord
-
- /*------------------------ graph_extension ----------------------------*/
-
- void graph_extension(point p)
- {
- real x = p.xcoord(); // if node is added, max.coord can change
- real y = p.ycoord();
-
- if ( x < G_XMIN ) G_XMIN = x;
- if ( x > G_XMAX ) G_XMAX = x;
- if ( y < G_YMIN ) G_YMIN = y;
- if ( y > G_YMAX ) G_YMAX = y;
-
- } // graph_extension
-
- /*-------------------------- init_window --------------------------*/
-
- void init_window()
- {
- int n_width = G_max_node_width - (2 * int( W_WIDTH / 100)); // new node_width
- int o_width = W.get_node_width();
-
- W.init(0,W_WIDTH,0);
-
- if (o_width >= 7) // '>7' = nodes with numbers
- {
- if (n_width<o_width) W.set_node_width(n_width);
- else W.set_node_width(o_width);
-
- W.set_line_width(2);
- }
-
- W.set_mode(xor_mode);
-
- } // init_window
-
- /*--------------------------- init_graph ----------------------------*/
-
- void init_graph()
- {
- node v;
- edge e;
-
- G_node_count = 0;
- G_edge_count = 0;
-
- forall_nodes(v,G) G_node_name[v] = G_node_count++; // rename nodes
-
- forall_edges(e,G) G[e] = G_edge_count++; // rename edges
-
- get_max_coord(); // test max.coord of graph G
-
- } // init_graph
-
- /*--------------------------- reset_graph ----------------------------*/
-
- void reset_graph()
- {
- G.clear();
-
- G_node_count = 0;
- G_edge_count = 0;
-
- G_XMAX = W.xmin(); // if now a node is added to the empty graph
- G_YMAX = W.ymin(); // it's coord. will become the max.coord. of G,
- G_XMIN = W.xmax(); // because the input must be on window W
- G_YMIN = W.ymax();
-
- } // reset_graph
-
- /*------------------------ scroll_window ------------------------------*/
-
- void scroll_window(real xpos,real ypos,int margin=1)
- {
- real x,y;
- real xdist,ydist;
- node n;
-
- if (margin == 1) // scroll to margin
- {
- xdist = xpos;
- ydist = ypos;
- }
- else // scroll user-define Direction
- {
- W.draw_filled_node(xpos,ypos);
-
- W.message(" user - scroll");
- W.read_mouse_seg(xpos,ypos,x,y);
-
- xdist = xpos - x;
- ydist = ypos - y;
- }
-
- G_XMIN += xdist; G_XMAX += xdist; // change max.coord. of graph G
- G_YMIN += ydist; G_YMAX += ydist;
-
- vector v(xdist,ydist);
-
- forall_nodes(n,G) // change coord. of nodes
- {
- G[n] = G[n] + v;
- }
-
- if (margin == 0) redraw_graph(); // user scroll
-
- } //scroll_window
-
- /*------------------------ center_graph ------------------------------*/
-
- void center_graph()
- {
- scroll_window((W.xmax() - W.xmin() - G_XMAX - G_XMIN) / 2.0,(W.ymax() - W.ymin() - G_YMAX - G_YMIN) / 2.0);
-
- } // center_graph
-
- /*------------------------ scroll_menu ------------------------------*/
-
- void scroll_menu()
- {
- int node_width = W.get_node_width();
- double margin_dist = (node_width / W.scale()) +1;
- double xpos,ypos;
-
- string header = form(" Scroll-Menu : scroll to which margin ??");
-
- panel P(header);
-
- P.button(" up-left ");
- P.button(" up ");
- P.button(" up-right ");
- P.new_button_line();
-
- P.button(" left ");
- P.button(" center ");
- P.button(" right ");
- P.new_button_line();
-
- P.button("down-left ");
- P.button(" down ");
- P.button("down-right");
- P.new_button_line();
-
- int scr_option = P.open();
-
- switch(scr_option)
- {
- case 0 : { xpos = W.xmin() - G_XMIN + margin_dist; // up-left
- ypos = W.ymax() - G_YMAX - margin_dist;
- break;
- }
-
-
- case 1 : { xpos = 0; // upper
- ypos = W.ymax() - G_YMAX - margin_dist;
- break;
- }
-
-
- case 2 : { xpos = W.xmax() - G_XMAX - margin_dist; // up-right
- ypos = W.ymax() - G_YMAX - margin_dist;
- break;
- }
-
-
- case 3 : { xpos = W.xmin() - G_XMIN + margin_dist; // left
- ypos = 0;
- break;
- }
-
-
- case 4 : { xpos = (W.xmax() - W.xmin() - G_XMAX - G_XMIN) / 2.0; // center
- ypos = (W.ymax() - W.ymin() - G_YMAX - G_YMIN) / 2.0;
- break;
- }
-
-
- case 5 : { xpos = W.xmax() - G_XMAX - margin_dist; // right
- ypos = 0;
- break;
- }
-
-
- case 6 : { xpos = W.xmin() - G_XMIN + margin_dist; // down-left
- ypos = W.ymin() - G_YMIN + margin_dist;
- break;
- }
-
-
- case 7 : { xpos = 0; // lower
- ypos = W.ymin() - G_YMIN + margin_dist;
- break;
- }
-
-
- case 8 : { xpos = W.xmax() - G_XMAX - margin_dist; // down-right
- ypos = W.ymin() - G_YMIN + margin_dist;
- break;
- }
-
- } // switch(scr_option)
-
- scroll_window(xpos,ypos);
-
- redraw_graph();
-
- } // scroll_menu
-
- /*------------------------- look_edge -------------------------------*/
-
- edge look_edge(node s,node t)
- {
- edge e;
-
- forall_adj_edges(e,s)
- {
- if (G.target(e) == t)
- {
- G.reset();
- return e;
- }
- }
-
- return nil;
-
- } // look_edge
-
- /*---------------------- node_intersection_test --------------------*/
-
- bool node_intersection_test(point cutp,node original = nil)
- {
- node n,testn;
- edge e;
- circle cutc(cutp,W.get_node_width() / W.scale() );
-
- // test intersection with other nodes
-
- forall_nodes(n,G)
- {
- if (n != original)
- {
- // test: 'original' is dropped on other node ??
-
- testn = get_node_at_point(cutp);
-
- if ((testn!=nil)&&(testn!=original))
- {
- new_error_node(cutp);
- G.reset();
- return true;
- }
-
- // test: 'original' overlaps on other node ??
-
- circle c(G[n],W.get_node_width() / W.scale() );
- list(point) schnitt = cutc.intersection(c);
-
- if (schnitt.length()>0)
- {
- new_error_node(cutp);
- G.reset();
- return true;
- }
- }
- }
-
- // test intersection with (non adjazent & inzident) edges
-
- forall_edges(e,G)
- {
- if ((G.source(e)!=original)&&(G.target(e)!=original))
- {
- segment seg(G[G.source(e)],G[G.target(e)]);
- list(point) schnitt = cutc.intersection(seg);
-
- if (schnitt.length()>0)
- {
- new_error_node(cutp);
- G.reset();
- return true;
- }
- }
- }
-
- return false;
-
- } // node_intersection_test
-
- /*--------------------- edge_intersection_test -----------------------*/
-
- bool edge_intersection_test(node s, node t,node ausnahme=nil)
- {
- node n;
- point p;
- segment st_seg(G[s],G[t]);
-
- // test intersection with other nodes
-
- forall_nodes(n,G)
- {
- if ((n!=s)&&(n!=t)&&(n!=ausnahme))
- {
- circle c(G[n],W.get_node_width() / W.scale() );
- list(point) schnitt = c.intersection(st_seg);
-
- if (schnitt.length()>0)
- {
- new_error_edge(st_seg);
-
- G.reset(); // reset iterator
- return true;
- }
- }
- }
-
- return false;
-
- } // edge_intersection_test
-
- /*-------------------------- node_resize ---------------------------*/
-
- void node_resize()
- {
- int old_node_width,new_node_width;
- int old_line_width,new_line_width;
- node n;
- bool schnitt = false;
-
- string size_header = form(" Resize Nodes : select form of nodes !!! ");
- string size[3];
-
- size[0] = " Cancel ";
- size[1] = " without numbers ";
- size[2] = " with numbers (select node_width) ";
-
- int size_option = W.read_panel(size_header,3,size);
-
- switch(size_option)
- {
- case 1 : new_node_width = 4;
- new_line_width = 1;
- newline;
- break;
-
- case 2 : newline;
- do {
- new_node_width = read_int("Resize Nodes : new size (7<=s<=15) -> ");
- } while ((new_node_width<7)||(new_node_width>G_max_node_width));
-
- new_line_width = 2;
- break;
- }
-
- if (size_option!=0)
- {
- old_node_width = W.set_node_width(new_node_width);
- old_line_width = W.set_line_width(new_line_width);
-
- redraw_graph();
-
- forall_nodes(n,G)
- {
- if (node_intersection_test(G[n],n)) schnitt = true;
- }
-
- if (schnitt)
- {
- overlap_message(false); // without redraw_graph()
- W.del_message();
-
- W.set_node_width(old_node_width);
- W.set_line_width(old_line_width);
-
- redraw_graph();
- cout<<"RESIZE -> refused\n";
- }
- else cout<<"RESIZE -> ok\n";
-
- }
-
- } // node_resize
-
- /*----------------------- move_subgraph ------------------------------*/
-
- void move_subgraph()
- {
- node n,s,t;
- edge e;
- real subx,suby,subX,subY,newx,newy;
- list(point) pol_list;
- list(node) moved_nodes;
- bool schnitt = false;
-
- cout<<"\nMOVE -> (click rectangle for location of subgraph)\n";
-
- W.read_mouse(subx,suby);
-
- point pl(subx,suby);pol_list.append(pl);
- W.draw_filled_node(pl);
-
- W.read_mouse_rect(subx,suby,subX,subY);
- W.draw_filled_node(pl);
-
- point pL(subx,subY);pol_list.append(pL);
- point pR(subX,subY);pol_list.append(pR);
- point pr(subX,suby);pol_list.append(pr);
-
- polygon pol(pol_list);
-
- W<<pol; // mark subgraph
-
- cout<<"MOVE -> (click point for location of left-down corner of new position)\n";
-
- W.read_mouse(newx,newy);
-
- W<<pol; // reset mark subgraph
-
- forall_edges(e,G) // clear old edges
- {
- s = G.source(e);
- t = G.target(e);
-
- if ( (moved_nodes.search(s)!=nil)||(moved_nodes.search(t)!=nil) )
- {
- draw_edge(e,white);
- }
- }
-
- // get new position of subgraph
-
- vector vec(newx - subx,newy - suby);
-
- forall_nodes(n,G)
- {
- if (pol.inside(G[n]))
- {
- draw_node(n); // clear old nodes
-
- G[n] = G[n] + vec;
- moved_nodes.append(n);
- }
- }
-
- // test : move subgraph possible
-
- forall(n,moved_nodes)
- {
- draw_node(n); // new position of nodes
-
- if (node_intersection_test(G[n],n)) schnitt = true;
- }
-
- forall_edges(e,G)
- {
- s = G.source(e);
- t = G.target(e);
-
- if ( (moved_nodes.search(s)!=nil)||(moved_nodes.search(t)!=nil) )
- {
- if (edge_intersection_test(s,t)) schnitt = true;
- else draw_edge(e);
- }
- }
-
- if (schnitt)
- {
- forall(n,moved_nodes) G[n] = G[n] + ( vec * -1 );
-
- overlap_message();
-
- cout<<"MOVE -> refused\n";
- }
- else
- {
- cout<<"MOVE -> ok\n";
- redraw_graph();
- still_saved = false;
- }
-
- get_max_coord();
-
- } // move_subgraph
-
- /*-------------------------- add_node -------------------------------*/
-
- node add_node(point p)
- {
- node v;
-
- if ( node_intersection_test(p) )
- {
- error("add node : node dropped on existing objects ... 'add' refused");
-
- return nil;
- }
-
- // add_node possible
-
- v = G.new_node(p);
-
- G_node_name[v] = G_node_count++;
- draw_node(v);
-
- graph_extension(p); // test max.coord. of graph G
-
- return v;
-
- } // add_node
-
- /*------------------------- add_edge ----------------------------------*/
-
- edge add_edge(node s,node t)
- {
- edge e;
-
- // test: e=(s,s) ??
-
- if (s==t)
- {
- error("add edge : source = target ... 'add' refused");
- return nil;
- }
-
- // test: edge e=(s,t) still exist ??
-
- if (look_edge(s,t)!=nil)
- {
- error("add edge : marked edge still exist ... 'add' refused");
- return nil;
- }
-
- if (edge_intersection_test(s,t))
- {
- error("add edge : marked edge dropped on existing nodes ... 'add' refused");
- return nil;
- }
-
- // add new edge to G
-
- e = G.new_edge(s,t);
-
- G[e] = G_edge_count++;
- draw_edge(e);
-
- return e;
-
- } // add_edge
-
- /*------------------------ delete_edge -------------------------------*/
-
- void delete_edge(edge e)
- {
- node s = G.source(e);
- node t = G.target(e);
-
- draw_edge(e,white);
- G.del_edge(e);
-
- edge reverse = look_edge(t,s);
-
- if (reverse!=nil) draw_edge(reverse);
-
- } // delete_edge
-
- /*--------------------------- move_node ------------------------------*/
-
- point move_node(node v)
- {
- real x,y;
- point p = G[v]; // old position
- node s,t;
- edge e;
- list(edge) e_list;
- bool schnitt_node = false;
- bool schnitt_edge = false;
-
- forall_edges(e,G) // get adj.+inz. edges
- {
- if ( (source(e)) == v || (target(e) == v) )
- {
- e_list.append(e);
- }
- }
-
- draw_node(v); // clear old position
-
- W.read_mouse_action(draw_node_cursor,x,y);
-
- point q(x,y); // new position
-
- forall(e,e_list) draw_edge(e,white); // clear old edges
-
-
- // test: intersection of v to other nodes
-
- schnitt_node = node_intersection_test(q,v);
-
- // test: intersection of v to other edges
-
- G[v] = q; // neue position zuweisen
- draw_node(v);
-
- forall(e,e_list)
- {
- s = G.source(e);
- t = G.target(e);
-
- if (edge_intersection_test(s,t)) schnitt_edge = true;
- else draw_edge(e);
- }
-
- if (schnitt_node) error("move node : node dropped on existing objects ... 'move' refused");
-
- if (schnitt_edge) error("move node : moved edge dropped on existing node ... 'move' refused");
-
- if ( schnitt_node || schnitt_edge )
- {
- G[v] = p;
- return p;
- }
-
- get_max_coord(); // test max.coord of graph G
- graph_extension(q);
-
- return q;
-
- } // move_node
-
- /*-------------------------- delete_node ----------------------------*/
-
- void delete_node(node v)
- {
- list(edge) ad_list,in_list;
- edge e;
-
- forall_edges(e,G)
- {
- if (source(e) == v) ad_list.append(e); // adj. edges
-
- if (target(e) == v) in_list.append(e); // inz. edges
- }
-
- forall(e,ad_list) delete_edge(e);
-
- if (in_list.length()>0)
- {
- warn("delete_node: incoming edges are deleted");
- forall(e,in_list) delete_edge(e);
- }
-
- draw_node(v);
- G.del_node(v);
-
- get_max_coord(); // test max.coord of graph G
-
- } // delete_node
-
- /*------------------------ insert_node -------------------------------*/
-
- node insert_node(edge e)
- {
- node s = G.source(e);
- node t = G.target(e);
-
- bool rev_exist = false;
- node n;
- edge reverse,e1,e2,e3,e4;
-
- real xs = G[s].xcoord();
- real ys = G[s].ycoord();
- real xt = G[t].xcoord();
- real yt = G[t].ycoord();
-
- point mid((xs+xt)/2, (ys+yt)/2);
-
- delete_edge(e);
-
- reverse = look_edge(t,s); // if (s,t) && (t,s) in G -> insert to both
- if (reverse != nil)
- {
- rev_exist = true;
- delete_edge(reverse);
- }
-
- output_enable = false;
-
- n = add_node(mid);
-
- if (n!=nil)
- {
- e1 = add_edge(s,n);
- e2 = add_edge(n,t);
-
- if (rev_exist)
- {
- e3 = add_edge(t,n);
- e4 = add_edge(n,s);
-
- draw_edge(e3); draw_edge(e4);
- }
-
- draw_edge(e1); draw_edge(e2);
-
- output_enable = true;
-
- return n;
- }
-
- // insert impossible
-
- output_enable = true;
-
- segment s1(G[s],mid);
- segment s2(mid,G[t]);
- new_error_edge(s1);
- new_error_edge(s2);
- overlap_message();
-
- add_edge(s,t);
- if (rev_exist) add_edge(t,s);
-
- error("insert edge : inserted node dropped on existing objects ... 'insert' refused");
-
- return nil;
-
- } // insert_node
-
- /*-------------------------- join_edges ------------------------------*/
-
- void join_edges(node n)
- {
- edge e;
- node s,t;
- bool refuse = false;
- list(edge) ad_list,in_list;
-
- forall_edges(e,G)
- {
- if (G.source(e)==n) ad_list.append(e); // adj. e = (n,?)
- if (G.target(e)==n) in_list.append(e); // inz. e = (?,n)
- }
-
- // degree-test
-
- if ((ad_list.length()==in_list.length())&&(0<ad_list.length()<=2))
- {
- list(node) n_list; // get participant nodes (n,s,t,...)
-
- forall(e,in_list)
- {
- s = G.source(e);
- t = G.target(e);
-
- if (n_list.search(s)==nil) n_list.append(s);
- if (n_list.search(t)==nil) n_list.append(t);
- }
-
- forall(e,ad_list)
- {
- s = G.source(e);
- t = G.target(e);
-
- if (n_list.search(s)==nil) n_list.append(s);
- if (n_list.search(t)==nil) n_list.append(t);
- }
-
- if (n_list.length()==3)
- {
- n_list.del_item(n_list.search(n)); // get s + t
- s = n_list.head();
- t = n_list.tail();
-
- if (! edge_intersection_test(s,t,n))
- {
- // 'join' possible
-
- if (look_edge(s,t)!=nil)
- {
- error("join edge : 'joined' edge still exist ... 'join' refused");
- return;
- }
-
- cout<<"\nJoin_Edge : (";
-
- forall(e,in_list)
- {
- cout<<" ("<<G_node_name[G.source(e)]<<"-"<<G_node_name[G.target(e)]<<")";
- delete_edge(e);
- }
-
- forall(e,ad_list)
- {
- cout<<" ("<<G_node_name[G.source(e)]<<"-"<<G_node_name[G.target(e)]<<")";
- delete_edge(e);
- }
-
- delete_node(n);
-
- cout<<" ) to (";
- cout<<" ("<<G_node_name[s]<<"-"<<G_node_name[t]<<")";
-
- add_edge(s,t);
-
- if (ad_list.length()==2)
- {
- add_edge(t,s);
- cout<<" ("<<G_node_name[t]<<"-"<<G_node_name[s]<<")";
- }
-
- cout<<" )\n";
-
- still_saved = false;
- }
- else
- {
- forall(e,ad_list) draw_edge(e,white);
- forall(e,in_list) draw_edge(e,white);
- draw_node(n);
-
- error("join edge : joined edge dropped on existing node ... 'join' refused");
- overlap_message();
- }
- }
- else refuse = true;
- }
- else refuse = true;
-
- if (refuse)
- {
- error("join edge : wrong degree of node ... 'join' refused");
- }
-
- } // join_edges
-
- /*---------------------------- unzoom ------------------------------*/
-
- void unzoom()
- {
- node n;
-
- bool schnitt = false;
- double minx = 0;
- double miny = 0;
-
- double factor = 2.0;
- double old_width = W_WIDTH;
- double new_width = (factor * W_WIDTH);
-
- if (new_width > 400) new_width = 400;
- W_WIDTH = new_width;
-
- double dist = (new_width - old_width) / 2;
- scroll_window(dist,dist);
-
- init_window(); // get new extension
- redraw_graph("without_W.clear");
-
- forall_nodes(n,G)
- {
- if (node_intersection_test(G[n],n)) schnitt = true;
- }
-
- if (schnitt)
- {
- overlap_message(false); // without redraw_graph()
-
- W_WIDTH = old_width;
- scroll_window(-dist,-dist);
- init_window();
- redraw_graph("without_W.clear");
-
- cout<<"\nUNZOOM -> refused\n";
- }
- else cout<<"\nUNZOOM -> ok\n";
-
- } // unzoom
-
- /*----------------------------- zoom ------------------------------*/
-
- void zoom()
- {
- real x,y,xp,yp;
- real xdist,ydist;
- real new_width;
-
- cout<<"\nZOOM -> click rectangle ( = screen after zoom)\n";
-
- W.read_mouse(xp,yp);
- W.draw_filled_node(xp,yp);
-
- W.read_mouse_rect(xp,yp,x,y);
-
- new_width = W_WIDTH * (abs(x - xp) / W_WIDTH);
-
- if (new_width>0)
- {
- W_WIDTH = new_width;
- init_window();
-
- if (xp < x) xdist = xp;
- else xdist = x;
-
- if (yp < y) ydist = yp;
- else ydist = y;
-
- scroll_window(-xdist,-ydist);
-
- redraw_graph("without_W.clear");
-
- cout<<"ZOOM -> ok\n";
- }
- else
- {
- error("zoom : grid distance out of range ... 'zoom' refused");
- cout<<"ZOOM -> refused\n";
- }
-
- } // zoom
-
- /*--------------------------- read_graph -----------------------------*/
-
- void read_graph(string str)
- {
- node v,s,t,knoten;
- edge e,kante;
- real readx,ready;
- double minx = 0;
- double miny = 0;
-
- GRAPH(point,int) HELP; // help graph
- GRAPH(point,int) old_G = G; // old Graph G
-
- if (str == "CANCEL")
- {
- cout<<"READ -> cancelled\n";
- return;
- }
-
- if (str == "")
- {
- read_graph(read_string("READ -> read file ( 'CANCEL' to stop ) : "));
- return;
- }
-
-
- int modus = HELP.read(str);
-
- if (modus == 1)
- {
- cout<<"(warning) read_graph: file '"<<str<<"' doesn't exist\n";
- read_graph(read_string("\nREAD -> read file ( 'CANCEL' to stop ) : "));
- return;
- }
-
- if (modus == 2)
- {
- cout<<"(warning) read_graph : graph '"<<str<<"' not created by Graph Editor\n";
- read_graph(read_string("\nREAD -> read file ( 'CANCEL' to stop ) : "));
- return;
- }
-
- if (modus == 3)
- {
- cout<<"(warning) read_graph : file '"<<str<<"' not represent a graph\n";
- read_graph(read_string("\nREAD -> read file ( 'CANCEL' to stop ) : "));
- return;
- }
-
- // move 'readed' graph to new position
-
- cout<<"READ -> (click left-down corner of new subgraph)\n";
-
- W.read_mouse(readx,ready);
-
- v = HELP.choose_node();
-
- if (v!=nil)
- {
- minx = HELP[v].xcoord();
- miny = HELP[v].ycoord();
- }
-
- forall_nodes(v,HELP) // min coord. of new_nodes
- {
- if (HELP[v].xcoord() < minx) minx = HELP[v].xcoord();
- if (HELP[v].ycoord() < miny) miny = HELP[v].ycoord();
- }
-
- vector resetvec(-minx,-miny);
- vector vec(readx,ready);
-
- forall_nodes(v,HELP) HELP[v] = HELP[v] + resetvec + vec;
-
-
- // eingelesenen Hilfs-Graphen HELP auf G kopieren
-
- bool complete = true;
- list(node) wrong_nodes;
-
- node_array(node) corr(HELP);
-
- output_enable = false; // no error and warning output
-
- forall_nodes(v,HELP)
- {
- knoten = add_node(HELP[v]);
-
- if (knoten!=nil) corr[v] = knoten;
- else
- {
- complete = false;
- wrong_nodes.append(v); // node not to G added
- new_error_node(HELP[v]);
- }
- }
-
- forall_edges(e,HELP)
- {
- s = HELP.source(e);
- t = HELP.target(e);
-
- if ( (wrong_nodes.search(s)==nil) && (wrong_nodes.search(t)==nil) )
- {
- kante = add_edge(corr[s],corr[t]);
-
- if (kante==nil) complete = false;
- }
- else
- {
- segment seg(G[s],G[t]);
- new_error_edge(seg);
- complete = false;
- }
- }
-
- output_enable = true;
- still_saved = false;
-
- if (complete) cout <<"READ -> ok\n";
- else
- {
- overlap_message(false); // without redraw_graph()
-
- if (W.confirm(" ??? read incomplete subgraph ??? "))
- {
- cout<<"READ -> incomplete\n";
- redraw_graph();
- }
- else
- {
- W.clear();
- reset_graph();
-
- output_enable = false; // no error and warning output
-
- node_array(node) old_corr(old_G);
-
- forall_nodes(v,old_G) old_corr[v] = add_node(old_G[v]);
- forall_edges(e,old_G) add_edge(old_corr[old_G.source(e)],old_corr[old_G.target(e)]);
- output_enable = true;
- still_saved = true;
-
- cout<<"READ -> refused\n";
- }
- }
-
- init_graph();
-
- } // read_graph
-
- /*-------------------------- load_graph ------------------------------*/
-
- void load_graph(string str)
- {
- node v,s,t,knoten;
- edge e,kante;
-
- GRAPH(point,int) HELP; // help graph
-
- if (str=="CANCEL")
- {
- cout<<"LOAD -> cancelled\n";
- return;
- }
-
- if (str=="")
- {
- load_graph(read_string("LOAD -> edit file ( 'CANCEL' to stop ) : "));
- return;
- }
-
-
- int modus = HELP.read(str);
-
- if (modus == 1)
- {
- cout<<"(warning) load_graph: file '"<<str<<"' doesn't exist\n";
- load_graph(read_string("\nLOAD -> edit file ( 'CANCEL' to stop ) : "));
- return;
- }
-
- if (modus == 2)
- {
- cout<<"(warning) load_graph : graph '"<<str<<"' not created by Graph Editor\n";
- load_graph(read_string("\nLOAD -> edit file ( 'CANCEL' to stop ) : "));
- return;
- }
-
- if (modus == 3)
- {
- cout<<"(warning) load_graph : file '"<<str<<"' doesn't represent a graph\n";
- load_graph(read_string("\nLOAD -> edit file ( 'CANCEL' to stop ) : "));
- return;
- }
-
- G_filename = str;
- reset_graph();
- W.clear();
-
- // eingelesenen Hilfs-Graphen HELP auf G kopieren
-
- bool complete = true;
- list(node) wrong_nodes;
-
- node_array(node) corr(HELP);
-
- forall_nodes(v,HELP)
- {
- knoten = add_node(HELP[v]);
-
- if (knoten!=nil) corr[v] = knoten;
- else
- {
- complete = false;
- wrong_nodes.append(v); // node not to G added
- new_error_node(HELP[v]);
- }
- }
-
- forall_edges(e,HELP)
- {
- s = HELP.source(e);
- t = HELP.target(e);
-
- if ( (wrong_nodes.search(s)==nil) && (wrong_nodes.search(t)==nil) )
- {
- kante = add_edge(corr[s],corr[t]);
-
- if (kante==nil) complete = false;
- }
- else
- {
- segment seg(G[s],G[t]);
- new_error_edge(seg);
- complete = false;
- }
- }
-
- if (complete) cout <<"LOAD -> ok\n";
- else
- {
- overlap_message();
- cout <<"LOAD -> incomplete\n";
- }
-
- init_graph();
-
- } //load_graph
-
- /*--------------------------- save_graph -----------------------------*/
- void save_graph(string f)
- {
- if (f!="")
- {
- G_filename = f;
- G.write(f);
-
- cout << "SAVE -> ok \n";
- still_saved = true;
- }
- else save_graph(read_string("SAVE -> write to file: "));
-
- } // save_graph
-
- /*-------------------------- save_test ------------------------------*/
-
- void save_test()
- {
- if (! still_saved)
- if (W.confirm(" ??? save old graph ??? "))
- {
- save_graph(read_string("\nSAVE -> write to file: "));
- }
-
- still_saved = true;
-
- } // save_test
-
- /*--------------------------- print_help -----------------------------*/
-
- void print_help()
- {
- W.clear();
- W.message(" ");
- W.message(" ");
- W.message(" ");
- W.message(" +----------------------------------------------+");
- W.message(" | Graph Edit |");
- W.message(" +----------------------------------------------+");
- W.message(" | BUTTON unshifted shifted |");
- W.message(" +----------------------------------------------+");
- W.message(" | LEFT: new node / move node delete node |");
- W.message(" | MIDDLE: new edge / insert node delete edge |");
- W.message(" | RIGHT: join edges / scroll Menu |");
- W.message(" +----------------------------------------------+");
- W.message(" ");
- W.message(" ");
- W.message(" ");
- W.message(" < Press Button > ");
-
- W.read_mouse();
- W.del_message();
- redraw_graph();
-
- }
-
- /*------------------------------ GED --------------------------------*/
-
- void GED(string filename)
- {
- node s,t,v,w,knoten;
- edge e,kante;
- real x,y;
- point p,q,pw;
- int key = 0;
- int fertig = 0;
- int k;
-
- int option = 0; // choosed option in menu
-
- G_node_count = 0; // reset counter
- G_edge_count = 0;
-
- W.init(0,80,0);
-
- W_save_mode = W.set_mode(xor_mode);
-
- W.set_node_width(12);
- W.set_line_width(2);
-
- G_XMAX = W.xmin();
- G_YMAX = W.ymin();
- G_XMIN = W.xmax();
- G_YMIN = W.ymax();
-
- cout<<"\n\n *** Planar Graph Editor ***\n\n( Menue : <Shift> right mouse_button )\n\n";
-
- cout<<"\n\n *** Graph Editor ***\n\n( Menue : <Shift> right mouse_button )\n\n";
-
- if (filename != "") load_graph(filename);
- else
- {
- center_graph();
- redraw_graph("without_W.clear");
- }
-
- init_graph();
-
- /* main - routine */
-
- while (option != 15) // option != Quit
- {
- key = W.read_mouse(x,y);
-
- p = point(x,y);
-
- v = get_node_at_point(p); // -> node clicked ?
-
- switch(key) {
-
- case 1: {
- if (v == nil)
- {
- knoten = add_node(p); /* new node */
-
- if (knoten!=nil)
- {
- cout<<"\nAdd Node : ("<<G_node_name[knoten]<<") \n";
- still_saved = false;
- }
- }
- else
- {
- move_node(v); /* move node */
-
- cout<<"\nMove Node : ("<<G_node_name[v]<<")\n";
- still_saved = false;
- }
-
- break;
-
- } // case 1
-
- case -1: {
- if (v != nil)
- {
- cout<<"\nDelete Node : ("<<G_node_name[v]<<")\n";
-
- delete_node(v); /* delete node */
-
- still_saved = false;
- }
- else error("delete node : no node at mouse-position ... 'delete' refused");
-
- break;
-
- } // case -1
-
- case 2: { /* new edge / insert node */
- if (v != nil)
- {
- p = G[v];
-
- do {
- W.message(" add edge / insert node");
- k = W.read_mouse_seg(p.xcoord(),p.ycoord(),x,y);
- W.del_message();
-
- pw = point(x,y);
-
- w = get_node_at_point(pw);
-
- if (w != nil)
- {
- if ((e=look_edge(v,w)) == nil)
- {
- kante = add_edge(v,w); /* new edge */
-
- if (kante!=nil)
- {
- cout<<"\nAdd Edge : ("<<G_node_name[v]<<"-"<<G_node_name[w]<<")\n";
- still_saved = false;
- }
- }
- else
- { /* insert node */
- s = G.source(e);
- t = G.target(e);
-
- knoten = insert_node(e);
-
- if (knoten!=nil)
- {
- cout<<"\nInsert Node : ("<<G_node_name[knoten]<<") to ("<<G_node_name[s]<<"-"<<G_node_name[t]<<")\n";
- still_saved = false;
- }
- }
- }
-
- } while ( w == nil && k == 2);
- }
-
- break;
-
- } // case 2
-
- case -2: { /* delete edge */
- if (v != nil)
- {
- p = G[v];
- W.message(" delete edge");
- W.read_mouse_seg(p.xcoord(),p.ycoord(),x,y);
- W.del_message();
-
- q = point(x,y);
- w = get_node_at_point(q);
-
- if (w != nil)
- {
- e = look_edge(v,w);
- if (e != nil)
- {
- cout<<"\nDelete Edge : ("<<G_node_name[v]<<"-"<<G_node_name[w]<<")\n";
- delete_edge(e);
-
- still_saved = false;
- }
- else error("delete edge : edge doesn't exist ... 'delete' refused");
- }
- }
-
- break;
-
- } // case -2
-
-
- case 3: { /* join edges / scroll */
-
- if (v != nil)
- {
- join_edges(v);
- }
- else
- {
- cout<<"\nUser Scroll : (click distance of window movement)\n";
- scroll_window(p.xcoord(),p.ycoord(),0); // user-scroll
- }
-
- break;
- }
-
-
- case -3: { /* Menu */
-
- string header = form("Graph Editor (file : \"%s\")",~G_filename);
-
- panel P(header);
-
- P.button(" Cancel ");
- P.new_button_line();
-
- P.button(" Help ");
- P.button(" Resize ");
- P.button(" Move ");
- P.button(" Scroll ");
- P.new_button_line();
-
- P.button(" Print ");
- P.button(" Redraw ");
- P.button(" Zoom ");
- P.button(" Unzoom ");
- P.new_button_line();
-
- P.button(" Load ");
- P.button(" Read ");
- P.button(" Save ");
- P.button("Save as ");
- P.new_button_line();
-
- P.button(" Clear ");
- P.button(" Quit ");
- P.new_button_line();
-
-
- option = P.open();
-
- W.del_message();
-
- switch (option) {
-
- case 1 : { print_help();
- break;
- }
-
- case 2 : { node_resize();
- break;
- }
-
- case 3 : { move_subgraph();
- break;
- }
-
- case 4 : { scroll_menu();
- break;
- }
-
- case 5 : { cout<<"\nPRINT -> graph `"<<G_filename<<"`\n";
- G.print();
- break;
- }
-
- case 6 : { redraw_graph();
- break;
- }
-
- case 7 : { zoom();
- break;
- }
-
- case 8 : { unzoom();
- break;
- }
-
- case 9 : { save_test();
- load_graph(read_string("\nLOAD -> edit file: "));
- break;
- }
-
- case 10 : { read_graph(read_string("\nREAD -> read file: "));
- break;
- }
-
- case 11 : { cout<<"\n";
- save_graph(G_filename);
- break;
- }
-
- case 12 : { save_graph(read_string("\nSAVE -> write to file: "));
- break;
- }
-
- case 14 : { save_test();
- W.clear();
- reset_graph();
- init_graph();
- G_filename="";
- cout<<"\nCLEAR -> Graph is empty\n";
- break;
- }
-
- } // switch(option)
-
- W.del_message();
-
- break;
-
- } // case -3
-
-
- } // switch(key)
-
- if ( (error_nodes.length()>0) || (error_edges.length()>0) )
- {
- overlap_message(); // Fehler ausgeben
- }
-
- } // while (option != 15)
-
- save_test();
-
- W.set_mode(W_save_mode);
- W.clear();
-
- cout<<"\nQUIT -> you leave 'Graph_Editor'\n";
- cout<<"\n\n *** Graph Editor ***\n\n";
-
- } // GED
-
- /*---------------------------- main -----------------------------------*/
-
- main(int argc, char** argv)
- {
- string f;
-
- if (argc < 2) f="";
- else f=argv[1];
-
-
- GED(f);
- }
-