[xiph-commits] r10156 - trunk/planarity
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Fri Oct 14 05:22:55 PDT 2005
Author: xiphmont
Date: 2005-10-14 05:22:47 -0700 (Fri, 14 Oct 2005)
New Revision: 10156
Added:
trunk/planarity/graph_region.c
trunk/planarity/graph_region.h
Modified:
trunk/planarity/Makefile
trunk/planarity/dialog_finish.c
trunk/planarity/dialog_finish.h
trunk/planarity/dialog_level_icons.c
trunk/planarity/gameboard.h
trunk/planarity/gameboard_draw_edge.c
trunk/planarity/gameboard_draw_main.c
trunk/planarity/gameboard_draw_score.c
trunk/planarity/gameboard_logic.c
trunk/planarity/gameboard_logic_buttonbar.c
trunk/planarity/gameboard_logic_fade.c
trunk/planarity/graph.c
trunk/planarity/graph.h
trunk/planarity/graph_arrange.c
trunk/planarity/graph_arrange.h
trunk/planarity/graph_generate.c
trunk/planarity/graph_generate.h
trunk/planarity/graph_generate_mesh1.c
trunk/planarity/graph_generate_mesh2.c
trunk/planarity/graph_score.c
trunk/planarity/main.c
trunk/planarity/version.h
Log:
Aside from any remaining bugs, gPlanarity is all done. No more wibbling around wasting time :-)
Modified: trunk/planarity/Makefile
===================================================================
--- trunk/planarity/Makefile 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/Makefile 2005-10-14 12:22:47 UTC (rev 10156)
@@ -25,7 +25,7 @@
gameboard_draw_score.c main.c gameboard_draw_selection.c\
timer.c gameboard_draw_vertex.c levelstate.c dialog_level.c\
dialog_level_icons.c gameboard_draw_text.c random.c graph_generate_data.c\
- gameboard_logic_fade.c graph_generate_mesh2.c
+ gameboard_logic_fade.c graph_generate_mesh2.c graph_region.c
OBJ = dialog_finish.o gameboard_logic.o dialog_pause.o gameboard_logic_button.o\
gameboard.o gameboard_logic_buttonbar.o gameboard_draw_box.o\
gameboard_logic_mouse.o gameboard_draw_button.o gameboard_logic_push.o\
@@ -35,7 +35,7 @@
gameboard_draw_score.o main.o gameboard_draw_selection.o\
timer.o gameboard_draw_vertex.o levelstate.o dialog_level.o\
dialog_level_icons.o gameboard_draw_text.o random.o graph_generate_data.o\
- gameboard_logic_fade.o graph_generate_mesh2.o
+ gameboard_logic_fade.o graph_generate_mesh2.o graph_region.o
CAIROVER = >= 1.0.0
GTKVER = >= 2.7.2
GCF = `pkg-config --static --cflags "gtk+-2.0 $(GTKVER) cairo $(CAIROVER)"`
@@ -68,13 +68,16 @@
$(STRIP) $(TARGET)
static:
+ pkg-config --cflags "gtk+-2.0 $(GTKVER) cairo $(CAIROVER)" 1>/dev/null
$(MAKE) static-target CFLAGS="-O2 -ffast-math $(GCF) $(ADD_DEF) "
$(STRIP) $(TARGET)
debug:
+ pkg-config --cflags "gtk+-2.0 $(GTKVER) cairo $(CAIROVER)" 1>/dev/null
$(MAKE) target CFLAGS="-g -Wall -W -Wno-unused-parameter -D__NO_MATH_INLINES $(GCF) $(ADD_DEF)"
profile:
+ pkg-config --cflags "gtk+-2.0 $(GTKVER) cairo $(CAIROVER)" 1>/dev/null
$(MAKE) target CFLAGS="-pg -g -O2 -ffast-math $(GCF) $(ADD_DEF)" LIBS="$(LIBS) -lgprof-helper "
clean:
Modified: trunk/planarity/dialog_finish.c
===================================================================
--- trunk/planarity/dialog_finish.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/dialog_finish.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -168,12 +168,12 @@
snprintf(buffer,160,"Base score: %d points",graphscore_get_raw_score(&g->g));
render_bordertext_centered(c,buffer, w/2,y);y+=24;
- if(graphscore_get_multiplier(&g->g)>1){
+ if(graphscore_get_multiplier_percent(&g->g)>100){
cairo_save(c);
set_font(c,16,16,0,1);
cairo_set_source_rgba (c, HIGH_COLOR);
- snprintf(buffer,160,"Objective Exceeded! x%d",graphscore_get_multiplier(&g->g));
+ snprintf(buffer,160,"Objective Exceeded! %d%%",graphscore_get_multiplier_percent(&g->g));
render_bordertext_centered(c,buffer, w/2,y);y+=24;
cairo_restore(c);
}
Modified: trunk/planarity/dialog_finish.h
===================================================================
--- trunk/planarity/dialog_finish.h 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/dialog_finish.h 2005-10-14 12:22:47 UTC (rev 10156)
@@ -26,7 +26,7 @@
#define FINISH_BUTTON_BORDER 35
#define FINISH_BUTTON_Y 25
-#define FINISHBOX_WIDTH 250
+#define FINISHBOX_WIDTH 270
#define FINISHBOX_HEIGHT 330
extern void finish_level_dialog(Gameboard *g);
Modified: trunk/planarity/dialog_level_icons.c
===================================================================
--- trunk/planarity/dialog_level_icons.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/dialog_level_icons.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -135,6 +135,7 @@
if(g->b.buttons_ready){
if(g->button_timer!=0)
g_source_remove(g->button_timer);
+ g->button_callback=0;
g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
}
}
@@ -153,6 +154,7 @@
if(g->b.buttons_ready){
if(g->button_timer!=0)
g_source_remove(g->button_timer);
+ g->button_callback = 0;
g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
}
}
@@ -173,6 +175,7 @@
dialog_level_oneicon_init(g,i-2,g->d.level_icons+i);
g->d.center_x = 0;
+ g->d.center_done=1;
g->d.level_lit = 2;
g->d.reset_deployed = 0;
@@ -212,12 +215,12 @@
if( iy+ih < ey ) continue;
if( iy > ey2 ) continue;
- if(l->icon){
+ if(l->icon && cairo_surface_status(l->icon)==CAIRO_STATUS_SUCCESS){
cairo_set_source_surface(c,l->icon,ix,iy);
cairo_paint_with_alpha(c,l->alpha);
}
- if(g->d.center_x==0){
+ if(g->d.center_x==0 && g->d.center_done){
if(i==2){
cairo_set_source_rgba (c, B_COLOR);
borderbox_path(c,ix+1.5,iy+1.5,iw-3,ih-3);
@@ -233,7 +236,7 @@
}
// render level related text
- if(g->d.center_x == 0 && c){
+ if(g->d.center_x == 0 && g->d.center_done && c){
char buffer[160];
// above text
@@ -291,6 +294,7 @@
int i;
if(g->d.center_x == 0){
+ g->d.center_done=1;
g_source_remove(g->d.icon_timer);
g->d.icon_timer=0;
@@ -301,6 +305,7 @@
return 0;
}
+ g->d.center_done=0;
for(i=0;i<5;i++)
if(g->d.level_icons[i].alpha)
invalidate_icon(g, g->d.level_icons+i);
@@ -372,9 +377,9 @@
if(g->d.level_lit == 1){
if(levelstate_prev()){
- if(!levelstate_in_progress())
- undeploy_reset_button(g);
-
+ if(!levelstate_in_progress())
+ undeploy_reset_button(g);
+
if(g->d.level_icons[4].icon)
cairo_surface_destroy(g->d.level_icons[4].icon);
for(i=4;i>=1;i--){
@@ -384,7 +389,7 @@
g->d.level_icons[0].icon=0;
dialog_level_oneicon_init(g,-2,g->d.level_icons);
- if(g->d.center_x==0)expose_full(g); // only needed to 'undraw' the text
+ if(g->d.center_x==0 && g->d.center_done)expose_full(g); // only needed to 'undraw' the text
g->d.center_x = g->d.level_icons[1].x - g->d.level_icons[2].x;
}
@@ -405,7 +410,7 @@
g->d.level_icons[4].icon=0;
dialog_level_oneicon_init(g,2,g->d.level_icons+4);
- if(g->d.center_x==0)expose_full(g); // only needed to 'undraw' the text
+ if(g->d.center_x==0 && g->d.center_done)expose_full(g); // only needed to 'undraw' the text
g->d.center_x = g->d.level_icons[3].x - g->d.level_icons[2].x;
Modified: trunk/planarity/gameboard.h
===================================================================
--- trunk/planarity/gameboard.h 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/gameboard.h 2005-10-14 12:22:47 UTC (rev 10156)
@@ -46,6 +46,7 @@
#define INTERSECTION_LINE_WIDTH 2
#define RESET_DELTA 2
+#define SCALE_DELTA 8
#define B_LINE 1
#define B_BORDER 6.5
@@ -143,6 +144,7 @@
dialog_level_oneicon level_icons[5];
int center_x;
+ int center_done;
int level_lit;
int reset_deployed;
@@ -179,6 +181,7 @@
int delayed_background;
int first_expose;
int hide_lines;
+ int realtime_background;
int show_intersections;
int finish_dialog_active;
int about_dialog_active;
@@ -330,4 +333,4 @@
extern void fade_cancel(Gameboard *g);
extern void fade_attached(Gameboard *g,vertex *v);
extern void fade_grabbed(Gameboard *g);
-
+extern void fade_marked(Gameboard *g);
Modified: trunk/planarity/gameboard_draw_edge.c
===================================================================
--- trunk/planarity/gameboard_draw_edge.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/gameboard_draw_edge.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -80,8 +80,6 @@
}
}
-
-
/* invalidate edge region for efficient expose *******************/
void invalidate_edges(GtkWidget *widget, vertex *v, int offx, int offy){
Modified: trunk/planarity/gameboard_draw_main.c
===================================================================
--- trunk/planarity/gameboard_draw_main.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/gameboard_draw_main.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -113,6 +113,8 @@
draw_vertex(c,v,g->vertex_grabbed);
} else if( v->selected ){
draw_vertex(c,v,g->vertex_sel);
+ if(v->fading)
+ draw_vertex_with_alpha(c,v,g->vertex_ghost,alpha);
} else if ( v == g->lit_vertex){
draw_vertex(c,v,g->vertex_lit);
} else if (v->attached_to_grabbed){
@@ -138,13 +140,51 @@
cairo_set_source_rgb(c,1,1,1);
cairo_paint(c);
-
+
if(!g->hide_lines){
setup_background_edge(c);
while(e){
- if(e->active){
+ if(e->active)
draw_edge(c,e);
+ e=e->next;
+ }
+ finish_edge(c);
+ }
+}
+
+static void draw_background_realpart(Gameboard *g,cairo_t *c,
+ int x, int y, int w, int h){
+ edge *e=g->g.edges;
+ int x2 = x+w-1+E_LINE;
+ int y2 = y+h-1+E_LINE;
+ x-=E_LINE;
+ y-=E_LINE;
+
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_paint(c);
+
+ if(!g->hide_lines){
+ setup_background_edge(c);
+ while(e){
+ int ex1 = e->A->x;
+ int ex2 = e->B->x;
+ int ey1 = e->A->y;
+ int ey2 = e->B->y;
+
+ if(ex1<ex2){
+ if(x>ex2 || x2<ex1){e=e->next;continue;}
+ }else{
+ if(x>ex1 || x2<ex2){e=e->next;continue;}
}
+
+ if(ey1<ey2){
+ if(y>ey2 || y2<ey1){e=e->next;continue;}
+ }else{
+ if(y>ey1 || y2<ey2){e=e->next;continue;}
+ }
+
+ draw_edge(c,e);
+
e=e->next;
}
finish_edge(c);
@@ -268,16 +308,18 @@
operations where expose combining causes huge, slow in-server alpha
blends that are undesirable) */
void gameboard_draw(Gameboard *g, int x, int y, int w, int h){
-
+ cairo_t *c = cairo_create(g->foreground);
if (w==0 || h==0) return;
-
- cairo_t *c = cairo_create(g->foreground);
-
- // copy background to foreground draw buffer
- cairo_set_source_surface(c,g->background,0,0);
- cairo_rectangle(c,x,y,w,h);
- cairo_fill(c);
+ if(g->realtime_background){
+ draw_background_realpart(g,c,x,y,w,h);
+ }else{
+ // copy background to foreground draw buffer
+ cairo_set_source_surface(c,g->background,0,0);
+ cairo_rectangle(c,x,y,w,h);
+ cairo_fill(c);
+ }
+
if(!g->pushed_curtain){
draw_foreground(g,c,x,y,w,h);
@@ -324,7 +366,7 @@
cairo_surface_t *s = cairo_image_surface_create_from_png(name);
- if(s==NULL)
+ if(s==NULL || cairo_surface_status(s)!=CAIRO_STATUS_SUCCESS)
fprintf(stderr,"ERROR: Could not load board icon \"%s\"\n",
name);
Modified: trunk/planarity/gameboard_draw_score.c
===================================================================
--- trunk/planarity/gameboard_draw_score.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/gameboard_draw_score.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -66,7 +66,7 @@
snprintf(level_string,160,"Level %d: %s",get_level_num()+1,get_level_desc());
snprintf(score_string,160,"Score: %d",graphscore_get_raw_score(&g->g));
- snprintf(mult_string,160,"x%d",graphscore_get_multiplier(&g->g));
+ snprintf(mult_string,160,"%d%%",graphscore_get_multiplier_percent(&g->g));
snprintf(int_string,160,"Intersections: %ld",g->g.active_intersections);
snprintf(obj_string,160,"Objective: %s",graphscore_objective_string(&g->g));
@@ -83,7 +83,7 @@
cairo_show_text (c, int_string);
cairo_move_to (c, 15, ty2);
cairo_show_text (c, score_string);
- if(graphscore_get_multiplier(&g->g)>1){
+ if(graphscore_get_multiplier_percent(&g->g)>100){
cairo_save(c);
cairo_set_source_rgba (c, HIGH_COLOR);
cairo_move_to (c, 15 + extentsS.width+10, ty2);
Modified: trunk/planarity/gameboard_logic.c
===================================================================
--- trunk/planarity/gameboard_logic.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/gameboard_logic.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -72,11 +72,109 @@
reenter_game(g);
}
+static void animate_verticies(Gameboard *g,
+ int *x_target,
+ int *y_target,
+ float *delta){
+ int flag=1,count=0;
+ vertex *v=g->g.verticies;
+ float *tx=alloca(g->g.vertex_num * sizeof(*tx));
+ float *ty=alloca(g->g.vertex_num * sizeof(*ty));
+
+ // hide intersections now; deactivating the verticies below will hide them anyway
+ g->show_intersections = 0;
+ g->realtime_background = 1;
+ update_full(g);
+
+ // deactivate all the verticies so they can be moved en-masse
+ // without graph metadata updates at each move
+ v=g->g.verticies;
+ while(v){
+ deactivate_vertex(&g->g,v);
+ tx[count]=v->x;
+ ty[count++]=v->y;
+ v=v->next;
+ }
+
+ // animate
+ while(flag){
+ count=0;
+ flag=0;
+
+ v=g->g.verticies;
+ while(v){
+ if(v->x!=x_target[count] || v->y!=y_target[count]){
+
+ float xd = x_target[count] - tx[count];
+ float yd = y_target[count] - ty[count];
+ float m = hypot(xd,yd);
+
+ tx[count]+= xd/m*delta[count];
+ ty[count]+= yd/m*delta[count];
+
+ invalidate_vertex(g,v);
+ invalidate_edges(GTK_WIDGET(g),v,0,0);
+
+ v->x = rint(tx[count]);
+ v->y = rint(ty[count]);
+
+ if( (v->x > x_target[count] && xd > 0) ||
+ (v->x < x_target[count] && xd < 0) ||
+ (v->y > y_target[count] && yd > 0) ||
+ (v->y < y_target[count] && yd < 0) ){
+ v->x = x_target[count];
+ v->y = y_target[count];
+ }else
+ flag=1;
+
+ invalidate_vertex(g,v);
+ invalidate_edges(GTK_WIDGET(g),v,0,0);
+
+ }
+ count++;
+ v=v->next;
+ }
+
+ gdk_window_process_all_updates();
+ gdk_flush();
+
+ }
+
+ // reactivate all the verticies
+ activate_verticies(&g->g);
+
+ // update the score
+ update_score(g);
+
+ // it's a reset; show lines is default. This also has the side
+ // effect of forcing a full board redraw and expose
+ g->realtime_background=0;
+ update_full(g);
+
+ // possible
+ if(g->g.active_intersections <= g->g.objective){
+ deploy_check(g);
+ }else{
+ undeploy_check(g);
+ }
+
+}
+
+
static void scale(Gameboard *g,double scale){
int x=g->g.width/2;
int y=g->g.height/2;
int sel = num_selected_verticies(&g->g);
vertex *v;
+ int *tx=alloca(g->g.vertex_num * sizeof(*tx));
+ int *ty=alloca(g->g.vertex_num * sizeof(*ty));
+ float *tm=alloca(g->g.vertex_num * sizeof(*ty));
+ int i=0;
+ int minx=0;
+ int maxx=g->g.width-1;
+ int miny=0;
+ int maxy=g->g.height-1;
+ int okflag=0;
// if selected, expand from center of selected mass
if(sel){
@@ -95,61 +193,63 @@
y = yac / sel;
}
- v=g->g.verticies;
- while(v){
-
- if(!sel || v->selected){
- float nx = (v->x - x)*scale+x;
- float ny = (v->y - y)*scale+y;
+ while(!okflag){
+ okflag=1;
+ i=0;
+ v=g->g.verticies;
+ while(v){
+
+ if(!sel || v->selected){
+ float nx = rint((v->x - x)*scale+x);
+ float ny = rint((v->y - y)*scale+y);
+ float m = hypot(nx - v->x,ny-v->y)/5;
+
+ if(nx<minx){
+ scale = (float)(minx-x) / (v->x-x);
+ okflag=0;
+ }
- if(nx<0 || nx>=g->g.width ||
- ny<0 || ny>=g->g.height){
+ if(nx>maxx){
+ scale = (float)(maxx-x) / (v->x - x);
+ okflag=0;
+ }
- float mag = hypot(nx-x,ny-y);
- if(mag){
- float ang = acos((nx-x) / mag);
- if(ny-y>0) ang = 2*M_PI-ang;
+ if(ny<miny){
+ scale = (float)(miny-y) / (v->y-y);
+ okflag=0;
+ }
- if(nx<0){
- mag *= -x/(nx-x);
- nx = cos(ang)*mag+x;
- ny = -sin(ang)*mag+y;
- }
-
- if(nx>=g->g.width){
- mag *= (g->g.width-x-1)/(nx-x);
- nx = cos(ang)*mag+x;
- ny = -sin(ang)*mag+y;
- }
-
- if(ny<0){
- mag *= -y/(ny-y);
- nx = cos(ang)*mag+x;
- ny = -sin(ang)*mag+y;
- }
-
- if(ny>=g->g.height){
- mag *= (g->g.height-y-1)/(ny-y);
- nx = cos(ang)*mag+x;
- ny = -sin(ang)*mag+y;
- }
+ if(ny>maxy){
+ scale = (float)(maxy-y) / (v->y - y);
+ okflag=0;
}
+ if(m<1)m=1;
+
+ tx[i] = rint(nx);
+ ty[i] = rint(ny);
+ tm[i++] = m;
+ }else{
+ tx[i] = v->x;
+ ty[i] = v->y;
+ tm[i++] = 0;
}
-
- deactivate_vertex(&g->g,v);
- v->x = rint(nx);
- v->y = rint(ny);
+ v=v->next;
}
- v=v->next;
}
- v=g->g.verticies;
- while(v){
- activate_vertex(&g->g,v);
- v=v->next;
+ if(scale>=.99999 && scale<=1.00001){
+ ungrab_verticies(&g->g);
+ v=g->g.verticies;
+ while(v){
+ if(v->x<2 || v->x>=g->g.width-3)v->grabbed=1;
+ if(v->y<2 || v->y>=g->g.height-3)v->grabbed=1;
+ v=v->next;
+ }
+ fade_marked(g);
+ ungrab_verticies(&g->g);
+ }else{
+ animate_verticies(g,tx,ty,tm);
}
-
- update_full(g);
}
static void gtk_main_quit_wrapper(Gameboard *g){
@@ -231,76 +331,20 @@
}
void reset_action(Gameboard *g){
- int flag=1;
vertex *v=g->g.verticies;
+ int *target_x = alloca(g->g.vertex_num * sizeof(*target_x));
+ int *target_y = alloca(g->g.vertex_num * sizeof(*target_y));
+ float *target_m = alloca(g->g.vertex_num * sizeof(*target_m));
+ int i=0;
- // hide intersections now; deactivating the verticies below will hide them anyway
- g->show_intersections = 0;
- expose_full(g);
- gdk_window_process_all_updates();
- gdk_flush();
-
- // deactivate all the verticies so they can be moved en-masse
- // without graph metadata updates at each move
while(v){
- deactivate_vertex(&g->g,v);
+ target_x[i]=v->orig_x;
+ target_y[i]=v->orig_y;
+ target_m[i++]=RESET_DELTA;
v=v->next;
}
- // animate
- while(flag){
- flag=0;
-
- v=g->g.verticies;
- while(v){
- int bxd = (g->g.width - g->g.orig_width) >>1;
- int byd = (g->g.height - g->g.orig_height) >>1;
- int vox = v->orig_x + bxd;
- int voy = v->orig_y + byd;
-
- if(v->x != vox || v->y != voy){
- flag=1;
-
- invalidate_vertex(g,v);
- if(v->x<vox){
- v->x+=RESET_DELTA;
- if(v->x>vox)v->x=vox;
- }else{
- v->x-=RESET_DELTA;
- if(v->x<vox)v->x=vox;
- }
- if(v->y<voy){
- v->y+=RESET_DELTA;
- if(v->y>voy)v->y=voy;
- }else{
- v->y-=RESET_DELTA;
- if(v->y<voy)v->y=voy;
- }
- invalidate_vertex(g,v);
- }
- v=v->next;
- }
- gdk_window_process_all_updates();
- gdk_flush();
-
- }
-
- // reactivate all the verticies
- activate_verticies(&g->g);
-
- // update the score
- update_score(g);
-
- // it's a reset; show lines is default. This also has the side
- // effect of forcing a full board redraw and expose
- set_hide_lines(g,0);
-
- // hey, the board could ahve come pre-solved
- if(g->g.active_intersections <= g->g.objective){
- deploy_check(g);
- }else{
- undeploy_check(g);
- }
+ animate_verticies(g,target_x,target_y,target_m);
// reset timer
set_timer(0);
Modified: trunk/planarity/gameboard_logic_buttonbar.c
===================================================================
--- trunk/planarity/gameboard_logic_buttonbar.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/gameboard_logic_buttonbar.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -151,6 +151,7 @@
if(g->button_timer!=0)
g_source_remove(g->button_timer);
+ g->button_callback=0;
g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
g->checkbutton_deployed=1;
}
@@ -169,6 +170,7 @@
if(g->button_timer!=0)
g_source_remove(g->button_timer);
+ g->button_callback=0;
g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
g->checkbutton_deployed=0;
}
Modified: trunk/planarity/gameboard_logic_fade.c
===================================================================
--- trunk/planarity/gameboard_logic_fade.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/gameboard_logic_fade.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -152,3 +152,21 @@
f->fade_timer = g_timeout_add(FADE_ANIM_INTERVAL, animate_fade, (gpointer)g);
}
+void fade_marked(Gameboard *g){
+ fade_state *f = &g->fade;
+ vertex *v = g->g.verticies;
+
+ /* If a fade is already in progress, cancel it */
+ fade_cancel(g);
+
+ while(v){
+ if(v->grabbed)
+ fade_add_vertex(f,v);
+ v=v->next;
+ }
+
+ f->count = FADE_FRAMES;
+
+ f->fade_timer = g_timeout_add(FADE_ANIM_INTERVAL, animate_fade, (gpointer)g);
+}
+
Modified: trunk/planarity/graph.c
===================================================================
--- trunk/planarity/graph.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -232,51 +232,60 @@
g->num_edges_active=0;
}
-int intersects(vertex *L1, vertex *L2, vertex *M1, vertex *M2, double *xo, double *yo){
+int intersectsV(vertex *L1, vertex *L2, vertex *M1, vertex *M2, double *xo, double *yo){
+ // edges that share a vertex don't intersect by definition
+ if(L1==M1) return 0;
+ if(L1==M2) return 0;
+ if(L2==M1) return 0;
+ if(L2==M2) return 0;
+
+ return intersects(L1->x,L1->y,L2->x,L2->y,M1->x,M1->y,M2->x,M2->y,xo,yo);
+}
+
+int intersects(int L1x, int L1y,
+ int L2x, int L2y,
+ int M1x, int M1y,
+ int M2x, int M2y,
+ double *xo, double *yo){
+
/* y = ax + b */
float La=0;
float Lb=0;
float Ma=0;
float Mb=0;
- // but first, edges that share a vertex don't intersect by definition
- if(L1==M1) return 0;
- if(L1==M2) return 0;
- if(L2==M1) return 0;
- if(L2==M2) return 0;
-
- if(L1->x != L2->x){
- La = (float)(L2->y - L1->y) / (L2->x - L1->x);
- Lb = (L1->y - L1->x * La);
+ if(L1x != L2x){
+ La = (float)(L2y - L1y) / (L2x - L1x);
+ Lb = (L1y - L1x * La);
}
- if(M1->x != M2->x){
- Ma = (float)(M2->y - M1->y) / (M2->x - M1->x);
- Mb = (M1->y - M1->x * Ma);
+ if(M1x != M2x){
+ Ma = (float)(M2y - M1y) / (M2x - M1x);
+ Mb = (M1y - M1x * Ma);
}
- if(L1->x == L2->x){
+ if(L1x == L2x){
// L is vertical line
- if(M1->x == M2->x){
+ if(M1x == M2x){
// M is also a vertical line
- if(L1->x == M1->x){
+ if(L1x == M1x){
// L and M vertical on same x, overlap?
- if(M1->y > L1->y &&
- M1->y > L2->y &&
- M2->y > L1->y &&
- M2->y > L2->y) return 0;
- if(M1->y < L1->y &&
- M1->y < L2->y &&
- M2->y < L1->y &&
- M2->y < L2->y) return 0;
+ if(M1y > L1y &&
+ M1y > L2y &&
+ M2y > L1y &&
+ M2y > L2y) return 0;
+ if(M1y < L1y &&
+ M1y < L2y &&
+ M2y < L1y &&
+ M2y < L2y) return 0;
{
- double y1=max( min(M1->y,M2->y), min(L1->y, L2->y));
- double y2=min( max(M1->y,M2->y), max(L1->y, L2->y));
+ double y1=max( min(M1y,M2y), min(L1y, L2y));
+ double y2=min( max(M1y,M2y), max(L1y, L2y));
- *xo = M1->x;
+ *xo = M1x;
*yo = (y1+y2)*.5;
}
@@ -289,39 +298,39 @@
// L vertical, M not vertical
// needed if L is vertical and M is horizontal
- if(L1->x < M1->x && L1->x < M2->x) return 0;
- if(L1->x > M1->x && L1->x > M2->x) return 0;
+ if(L1x < M1x && L1x < M2x) return 0;
+ if(L1x > M1x && L1x > M2x) return 0;
{
- float y = Ma*L1->x + Mb;
+ float y = Ma*L1x + Mb;
- if(y < L1->y && y < L2->y) return 0;
- if(y > L1->y && y > L2->y) return 0;
- if(y < M1->y && y < M2->y) return 0;
- if(y > M1->y && y > M2->y) return 0;
+ if(y < L1y && y < L2y) return 0;
+ if(y > L1y && y > L2y) return 0;
+ if(y < M1y && y < M2y) return 0;
+ if(y > M1y && y > M2y) return 0;
- *xo = L1->x;
+ *xo = L1x;
*yo=y;
}
}
}else{
- if(M1->x == M2->x){
+ if(M1x == M2x){
// M vertical, L not vertical
// needed if L is vertical and M is horizontal
- if(M1->x < L1->x && M1->x < L2->x) return 0;
- if(M1->x > L1->x && M1->x > L2->x) return 0;
+ if(M1x < L1x && M1x < L2x) return 0;
+ if(M1x > L1x && M1x > L2x) return 0;
{
- float y = La*M1->x + Lb;
+ float y = La*M1x + Lb;
- if(y < L1->y && y < L2->y) return 0;
- if(y > L1->y && y > L2->y) return 0;
- if(y < M1->y && y < M2->y) return 0;
- if(y > M1->y && y > M2->y) return 0;
+ if(y < L1y && y < L2y) return 0;
+ if(y > L1y && y > L2y) return 0;
+ if(y < M1y && y < M2y) return 0;
+ if(y > M1y && y > M2y) return 0;
- *xo = M1->x;
+ *xo = M1x;
*yo=y;
}
}else{
@@ -332,20 +341,20 @@
if(Mb != Lb) return 0;
// two segments on same line...
- if(M1->x > L1->x &&
- M1->x > L2->x &&
- M2->x > L1->x &&
- M2->x > L2->x) return 0;
- if(M1->x < L1->x &&
- M1->x < L2->x &&
- M2->x < L1->x &&
- M2->x < L2->x) return 0;
+ if(M1x > L1x &&
+ M1x > L2x &&
+ M2x > L1x &&
+ M2x > L2x) return 0;
+ if(M1x < L1x &&
+ M1x < L2x &&
+ M2x < L1x &&
+ M2x < L2x) return 0;
{
- double x1=max( min(M1->x,M2->x), min(L1->x, L2->x));
- double x2=min( max(M1->x,M2->x), max(L1->x, L2->x));
- double y1=max( min(M1->y,M2->y), min(L1->y, L2->y));
- double y2=min( max(M1->y,M2->y), max(L1->y, L2->y));
+ double x1=max( min(M1x,M2x), min(L1x, L2x));
+ double x2=min( max(M1x,M2x), max(L1x, L2x));
+ double y1=max( min(M1y,M2y), min(L1y, L2y));
+ double y2=min( max(M1y,M2y), max(L1y, L2y));
*xo = (x1+x2)*.5;
*yo = (y1+y2)*.5;
@@ -357,10 +366,10 @@
// finally typical case: L and M have different non-infinite slopes
float x = (Mb-Lb) / (La - Ma);
- if(x < L1->x && x < L2->x) return 0;
- if(x > L1->x && x > L2->x) return 0;
- if(x < M1->x && x < M2->x) return 0;
- if(x > M1->x && x > M2->x) return 0;
+ if(x < L1x && x < L2x) return 0;
+ if(x > L1x && x > L2x) return 0;
+ if(x < M1x && x < M2x) return 0;
+ if(x > M1x && x > M2x) return 0;
*xo = x;
*yo = La*x + Lb;
@@ -378,7 +387,7 @@
while(test){
if(test != e && test->active){
double x,y;
- if(intersects(e->A,e->B,test->A,test->B,&x,&y)){
+ if(intersectsV(e->A,e->B,test->A,test->B,&x,&y)){
add_paired_intersection(e,test,x,y);
g->active_intersections++;
Modified: trunk/planarity/graph.h
===================================================================
--- trunk/planarity/graph.h 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph.h 2005-10-14 12:22:47 UTC (rev 10156)
@@ -110,9 +110,11 @@
extern edge *new_edge(vertex *A, vertex *B);
extern void release_edge_list(edge_list *el);
extern void insert_edge(graph *g, edge *e);
-extern int intersects(vertex *L1, vertex *L2, vertex *M1, vertex *M2,
+extern int intersectsV(vertex *L1, vertex *L2, vertex *M1, vertex *M2,
+ double *xo, double *yo);
+extern int intersects(int L1x, int L1y, int L2x, int L2y,
+ int M1x, int M1y, int M2x, int M2y,
double *xo, double *yo);
-
extern void move_vertex(graph *g, vertex *v, int x, int y);
extern void grab_vertex(graph *g, vertex *v);
extern void grab_selected(graph *g);
@@ -141,8 +143,8 @@
extern int graph_read(graph *g, FILE *f);
extern void graph_release(graph *g);
-extern int graphscore_get_score(graph *g);
-extern int graphscore_get_raw_score(graph *g);
-extern int graphscore_get_multiplier(graph *g);
-extern int graphscore_get_bonus(graph *g);
+extern int graphscore_get_score(graph *g);
+extern int graphscore_get_raw_score(graph *g);
+extern int graphscore_get_multiplier_percent(graph *g);
+extern int graphscore_get_bonus(graph *g);
extern char *graphscore_objective_string(graph *g);
Modified: trunk/planarity/graph_arrange.c
===================================================================
--- trunk/planarity/graph_arrange.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_arrange.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -30,6 +30,7 @@
#include "random.h"
#include "gameboard.h"
#include "graph_arrange.h"
+#include "graph_region.h"
void arrange_verticies_circle(graph *g, float off1, float off2){
vertex *v = g->verticies;
@@ -203,35 +204,245 @@
}
}
-void arrange_verticies_cloud(graph *g){
- vertex *v = g->verticies;
- int n = g->vertex_num;
+void arrange_region_star(graph *g){
+ region_init();
+ region_new_area(400,45,1);
+ region_line_to(340,232);
+ region_line_to(143,232);
+ region_line_to(303,347);
+ region_line_to(241,533);
+ region_line_to(400,417);
+ region_line_to(559,533);
+ region_line_to(497,347);
+ region_line_to(657,232);
+ region_line_to(460,232);
+ region_close_line();
+ region_layout(g);
+}
+
+void arrange_region_rainbow(graph *g){
+ region_init();
+ region_new_area(40,500,2);
+ region_arc_to(760,500,-M_PI);
+ region_line_to(660,500);
+ region_arc_to(200,500,M_PI);
+ region_close_line();
+ region_layout(g);
+}
+
+void arrange_region_dashed_circle(graph *g){
int bw=g->orig_width;
int bh=g->orig_height;
- int radiusx=min(bw,bh)*.55;
- int radiusy=min(bw,bh)*.40;
+ int radius=min(bw,bh)*.45;
int i;
-
- // first half form an outer perimiter
- for(i=0;i<n/2;i++){
- v->x = rint( radiusx * cos( i*M_PI*4./n) + (bw>>1));
- v->y = rint( radiusy * sin( i*M_PI*4./n) + (bh>>1));
- v=v->next;
+ region_init();
+
+ for(i=0;i<20;i+=2){
+ float phi0=(M_PI*2.f/20*(i-.5));
+ float phi1=(M_PI*2.f/20*(i+.5));
+ int x1= cos(phi0)*radius+bw/2;
+ int y1= -sin(phi0)*radius+bh/2;
+ int x2= cos(phi1)*radius+bw/2;
+ int y2= -sin(phi1)*radius+bh/2;
+ region_new_area(x1,y1,3);
+ region_arc_to(x2,y2,M_PI/10);
}
+ region_layout(g);
+}
- // second third form an inner perimiter
+void arrange_region_bifur(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
- for(;i<n/2+n/3;i++){
- v->x = rint( radiusx * .7 * cos( i*M_PI*6./n) + (bw>>1));
- v->y = rint( radiusy * .7 * sin( i*M_PI*6./n) + (bh>>1));
- v=v->next;
+ region_init();
+ region_new_area(21,60,2);
+ region_line_to(bw/2-130,60);
+ region_arc_to(bw/2+130,60,-M_PI*.25);
+ region_line_to(bw-21,60);
+
+ region_new_area(21,bh-60,1);
+ region_line_to(bw/2-130,bh-60);
+ region_arc_to(bw/2+130,bh-60,M_PI*.25);
+ region_line_to(bw-21,bh-60);
+
+ region_layout(g);
+
+}
+
+void arrange_region_dairyqueen(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45;
+
+ float phi0=(M_PI/2 + M_PI*2.f/8);
+ float phi1=(M_PI/2 - M_PI*2.f/8);
+
+ int x1= cos(phi0)*radius+bw/2;
+ int x2= cos(phi1)*radius+bw/2;
+
+ int y1= -sin(phi0)*radius+bh/2;
+ int y2= sin(phi0)*radius+bh/2;
+
+ region_init();
+
+ region_new_area(x1,y1,2);
+ region_arc_to(x2,y1,-M_PI/2);
+ region_line_to(750,bh/2);
+ region_line_to(x2,y2);
+ region_arc_to(x1,y2,-M_PI/2);
+ region_line_to(50,bh/2);
+ region_close_line();
+
+ region_layout(g);
+}
+
+void arrange_region_cloud(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45-20;
+ int i=0;
+ float phi0=(M_PI*2.f/20*(i-.5)),phi1;
+ int x1= cos(phi0)*radius+bw/2,x2;
+ int y1= -sin(phi0)*radius+bh/2,y2;
+
+ region_init();
+ region_new_area(x1,y1,1);
+ for(i=0;i<19;i++){
+ phi1=(M_PI*2.f/20*(i+.5));
+ x2= cos(phi1)*radius+bw/2;
+ y2= -sin(phi1)*radius+bh/2;
+ region_arc_to(x2,y2,M_PI*.7);
}
+ region_close_arc(M_PI*.7);
- for(;i<n;i++){
- v->x = rint( radiusx * .4 * cos( i*M_PI*12./n) + (bw>>1));
- v->y = rint( radiusy * .4 * sin( i*M_PI*12./n) + (bh>>1));
- v=v->next;
+ region_layout(g);
+}
+
+void arrange_region_ring(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45;
+
+ region_init();
+ region_circle(bw/2,bh/2,radius,3);
+ region_circle(bw/2,bh/2,radius*.4,1);
+ region_layout(g);
+}
+
+void arrange_region_storm(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45;
+ int i=0;
+
+ region_init();
+
+ for(i=0;i<10;i++){
+ float phi0=(M_PI*2.f/10*(i-.5));
+ float phi1=(M_PI*2.f/10*(i+.5));
+ int x1= cos(phi0)*radius+bw/2;
+ int y1= -sin(phi0)*radius+bh/2;
+ int x2= cos(phi1)*radius*.8+bw/2;
+ int y2= -sin(phi1)*radius*.8+bh/2;
+
+ region_new_area(x1,y1,1);
+ region_arc_to(x2,y2,M_PI*.2);
}
+ region_circle(bw/2,bh/2,radius*.2,0);
+
+ region_layout(g);
}
+
+void arrange_region_target(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45;
+
+ region_init();
+ region_circle(bw/2,bh/2,radius,3);
+ region_circle(bw/2,bh/2,radius*.5,1);
+ region_circle(bw/2,bh/2,radius*.35,3);
+
+ region_layout(g);
+}
+
+void arrange_region_plus(graph *g){
+ region_init();
+
+ region_new_area(316,43,2);
+ region_arc_to(483,43,-M_PI*2/10);
+ region_line_to(483,216);
+ region_line_to(656,216);
+ region_arc_to(656,384,-M_PI*2/10);
+ region_line_to(483,384);
+ region_line_to(483,556);
+ region_arc_to(316,556,-M_PI*2/10);
+ region_line_to(316,384);
+ region_line_to(143,384);
+ region_arc_to(143,216,-M_PI*2/10);
+ region_line_to(316,216);
+ region_close_line();
+
+ region_layout(g);
+}
+
+void arrange_region_hole3(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45;
+
+ region_init();
+ region_circle(bw/2,bh/2,radius,3);
+
+ region_new_area(400,200,2);
+ region_line_to(313,349);
+ region_line_to(487,349);
+ region_close_line();
+ region_layout(g);
+}
+
+void arrange_region_hole4(graph *g){
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45;
+
+ region_init();
+ region_circle(bw/2,bh/2,radius,3);
+
+ region_new_area(325,225,1);
+ region_line_to(475,225);
+ region_line_to(475,375);
+ region_line_to(325,375);
+ region_close_line();
+ region_layout(g);
+}
+
+void arrange_region_ovals(graph *g){
+
+
+ region_init();
+ region_new_area(270,163,2);
+ region_arc_to(530,163,-M_PI*.99);
+ region_line_to(530,437);
+ region_arc_to(270,437,-M_PI*.99);
+ region_close_line();
+
+ region_new_area(80,263,2);
+ region_arc_to(230,263,-M_PI*.99);
+ region_line_to(230,337);
+ region_arc_to(80,337,-M_PI*.99);
+ region_close_line();
+
+ region_new_area(570,263,2);
+ region_arc_to(720,263,-M_PI*.99);
+ region_line_to(720,337);
+ region_arc_to(570,337,-M_PI*.99);
+ region_close_line();
+
+
+ region_layout(g);
+
+
+}
Modified: trunk/planarity/graph_arrange.h
===================================================================
--- trunk/planarity/graph_arrange.h 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_arrange.h 2005-10-14 12:22:47 UTC (rev 10156)
@@ -33,4 +33,17 @@
extern void arrange_verticies_mesh(graph *g, int width, int height);
extern void arrange_verticies_nastymesh(graph *g, int w, int h, vertex **flat);
-extern void arrange_verticies_cloud(graph *g);
+
+extern void arrange_region_star(graph *g);
+extern void arrange_region_rainbow(graph *g);
+extern void arrange_region_dashed_circle(graph *g);
+extern void arrange_region_bifur(graph *g);
+extern void arrange_region_dairyqueen(graph *g);
+extern void arrange_region_cloud(graph *g);
+extern void arrange_region_ring(graph *g);
+extern void arrange_region_storm(graph *g);
+extern void arrange_region_target(graph *g);
+extern void arrange_region_plus(graph *g);
+extern void arrange_region_hole3(graph *g);
+extern void arrange_region_hole4(graph *g);
+extern void arrange_region_ovals(graph *g);
Modified: trunk/planarity/graph_generate.c
===================================================================
--- trunk/planarity/graph_generate.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_generate.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -40,52 +40,115 @@
int unlock;
} gen_instance;
-#define FINITE_LEVELS 23
+#define FINITE_LEVELS 79
static gen_instance i_list[FINITE_LEVELS]={
- {"simple", 1, "A Small Beginning", generate_simple, 1.,1., 1 }, // 1
- {"simple", 2, "My First Real Level(tm)", generate_simple, 1.,1., 2 }, // 2
- {"data", 0, "My First Mission Impossible(tm)", generate_data, 20.,1., 3 }, // 3
- {"simple", 3, "Larger But Not Harder", generate_simple, 1.,1., 2 }, // 4
- {"crest", 5, "The Trick Is It's Easy", generate_crest, 1.,1., 2 }, // 5
+ {"simple", 1, "A Small Beginning", generate_simple, 1.,4., 1 }, // 1
+ {"simple", 2, "My First Real Level(tm)", generate_simple, 1.,4., 2 }, // 2
+ {"data", 0, "My First Mission Impossible(tm)", generate_data, 20.,4., 3 }, // 3
+ {"simple", 3, "Larger But Not Harder", generate_simple, 1.,4., 2 }, // 4
+ {"crest", 5, "The Trick Is It's Easy", generate_crest, 1.,4., 2 }, // 5
- {"simple", 4, "Practice Before the Handbasket: One of Three", generate_simple, 1.,1., 2 }, // 6
- {"simple", 5, "Practice Before the Handbasket: Two of Three", generate_simple, 1.,1., 2 }, // 7
- {"simple", 6, "Practice Before the Handbasket: Three of Three", generate_simple, 1.,1., 2 }, // 8
+ {"simple", 4, "Practice Before the Handbasket: One of Three", generate_simple, 1.,4., 2 }, // 6
+ {"simple", 5, "Practice Before the Handbasket: Two of Three", generate_simple, 1.,4., 2 }, // 7
+ {"simple", 6, "Practice Before the Handbasket: Three of Three", generate_simple, 1.,4., 2 }, // 8
- {"sparse", 4, "Tough and Stringy", generate_sparse, 1.2,1., 2 }, // 9
- {"sparse", 5, "Threadbare", generate_sparse, 1.2,1., 2 }, // 10
+ {"sparse", 4, "Tough and Stringy", generate_sparse, 1.2,4., 2 }, // 9
+ {"sparse", 5, "Threadbare", generate_sparse, 1.2,4., 2 }, // 10
- {"nasty", 4, "The Bumpy Circles Are Slightly More Difficult", generate_nasty, 1.5,1., 3 }, // 11
- {"nasty", 5, "Three is a Magic Number", generate_nasty, 1.5,1., 3 }, // 12
- {"nasty", 6, "Last Call For (Sort of) Triangles (For Now)", generate_nasty, 1.5,1., 3 }, // 13
+ {"nasty", 4, "The Bumpy Circles Are Slightly More Difficult", generate_nasty, 1.5,4., 3 }, // 11
+ {"nasty", 5, "Three is a Magic Number", generate_nasty, 1.5,4., 3 }, // 12
+ {"nasty", 6, "Last Call For (Sort of) Triangles (For Now)", generate_nasty, 1.5,4., 3 }, // 13
- {"free", 4, "Something Only Subtly Different", generate_freeform, 1.5,1., 3 }, // 14
- {"free", 5, "It Can Roll! Granted, Not Very Well", generate_freeform, 1.5,1., 3 }, // 15
- {"free", 6, "If You Squint, It's a Round Brick", generate_freeform, 1.5,1., 3 }, // 16
+ {"free", 4, "Something Only Subtly Different", generate_freeform, 1.5,4., 3 }, // 14
+ {"free", 5, "It Can Roll! Granted, Not Very Well", generate_freeform, 1.5,4., 3 }, // 15
+ {"free", 6, "If You Squint, It's a Round Brick", generate_freeform, 1.5,4., 3 }, // 16
- {"rogue", 5, "A New Objective", generate_rogue, 1.6,1., 3 }, // 17
- {"rogue", 6, "How Low Can You Go?", generate_rogue, 1.6,1., 3 }, // 18
- {"rogue", 7, "Military Industrial Complex", generate_rogue, 1.6,1., 4 }, // 19
+ {"rogue", 5, "A New Objective", generate_rogue, 1.6,4., 3 }, // 17
+ {"rogue", 6, "How Low Can You Go?", generate_rogue, 1.6,4., 3 }, // 18
+ {"rogue", 7, "Military Industrial Complex", generate_rogue, 1.6,4., 4 }, // 19
- {"embed", 4, "The Hexagon is a Subtle and Wily Beast", generate_embed, 2.,1., 4 }, // 20
- {"embed", 5, "No, Really, The Hexagon Puzzles Are Harder", generate_embed, 3.,1., 5 }, // 21
- {"embed", 6, "Cursed? Call 1-800-HEX-A-GON Today!", generate_embed, 4.,1., 6 }, // 22
+ {"embed", 4, "The Hexagon is a Subtle and Wily Beast", generate_embed, 2.,4., 4 }, // 20
+ {"embed", 5, "No, Really, The Hexagon Puzzles Are Harder", generate_embed, 3.,4., 5 }, // 21
+ {"embed", 6, "Cursed? Call 1-800-HEX-A-GON Today!", generate_embed, 4.,4., 6 }, // 22
- {"simple", 7, "Round but Straightforward", generate_simple, 1.,1., 4 }, // 23
+ {"simple", 7, "Round but Straightforward", generate_simple, 1.,4., 4 }, // 23
- //{"cloud", 9, "More of a Mess Than Usual", generate_mesh_1_cloud, 2.,1., 3 }, // 9
+ {"shape", 0, "A Star Is Born... Then Solved", generate_shape, 1.,2., 6 }, // 24
+ {"shape", 1, "Oh, Rain*bows*...", generate_shape, 1.,2., 6 }, // 25
+ {"shape", 2, "Solve Along the Dotted Line", generate_shape, 1.,2., 6 }, // 26
+ {"shape", 3, "Using All Available Space", generate_shape, 1.,2., 6 }, // 27
+ {"shape", 4, "Brainfreeze", generate_shape, 1.,2., 6 }, // 28
+ {"shape", 6, "Tropical Storm Invest", generate_shape, 1.,2., 6 }, // 30
+
+ {"dense", 8, "Algorithm: Original/Dense (Order: 8)", generate_dense, .8,1., 5 }, // 31
+ {"simple", 8, "Algorithm: Original (Order: 8)", generate_simple, 1.,1., 6 }, // 32
+ {"sparse", 8, "Algorithm: Original/Sparse (Order: 8)",generate_sparse, 1.2,1., 7 }, // 33
+ {"nasty", 8, "Algorithm: Nasty (Order: 8)", generate_nasty, 1.5,1., 8 }, // 34
+ {"free", 8, "Algorithm: Freeform/4 (Order: 8)", generate_freeform, 1.5,1., 9 }, // 35
+ {"rogue", 8, "Algorithm: Rogue (Order: 8)", generate_rogue, 1.6,1.,10 }, // 36
+ {"embed", 8, "Algorithm: Embed (Order: 8)", generate_embed, 4.,1.,10 }, // 37
+ {"shape", 7, "Operator", generate_shape, 1.,2.,10 }, // 38
+
+ {"dense", 9, "Algorithm: Original/Dense (Order: 9)", generate_dense, .8,1., 5 }, // 39
+ {"simple", 9, "Algorithm: Original (Order: 9)", generate_simple, 1.,1., 6 }, // 40
+ {"sparse", 9, "Algorithm: Original/Sparse (Order: 9)",generate_sparse, 1.2,1., 7 }, // 41
+ {"nasty", 9, "Algorithm: Nasty (Order: 9)", generate_nasty, 1.5,1., 8 }, // 42
+ {"free", 9, "Algorithm: Freeform/4 (Order: 9)", generate_freeform, 1.5,1., 9 }, // 43
+ {"rogue", 9, "Algorithm: Rogue (Order: 9)", generate_rogue, 1.6,1.,10 }, // 44
+ {"embed", 9, "Algorithm: Embed (Order: 9)", generate_embed, 4.,1.,10 }, // 45
+ {"shape", 8, "The Inside Is Pointy", generate_shape, 1.,2.,10 }, // 46
+
+ {"dense", 10, "Algorithm: Original/Dense (Order: 10)", generate_dense, .8,1., 5 }, // 47
+ {"simple",10, "Algorithm: Original (Order: 10)", generate_simple, 1.,1., 6 }, // 48
+ {"sparse",10, "Algorithm: Original/Sparse (Order: 10)",generate_sparse, 1.2,1., 7 }, // 49
+ {"nasty", 10, "Algorithm: Nasty (Order: 10)", generate_nasty, 1.5,1., 8 }, // 50
+ {"free", 10, "Algorithm: Freeform/4 (Order: 10)", generate_freeform, 1.5,1., 9 }, // 51
+ {"rogue", 10, "Algorithm: Rogue (Order: 10)", generate_rogue, 1.6,1.,10 }, // 52
+ {"embed", 10, "Algorithm: Embed (Order: 10)", generate_embed, 4.,1.,10 }, // 53
+ {"shape", 9, "Riches and Good Luck", generate_shape, 1.,2.,10 }, // 54
+
+ {"dense", 11, "Algorithm: Original/Dense (Order: 11)", generate_dense, .8,1., 5 }, // 55
+ {"simple",11, "Algorithm: Original (Order: 11)", generate_simple, 1.,1., 6 }, // 56
+ {"sparse",11, "Algorithm: Original/Sparse (Order: 11)",generate_sparse, 1.2,1., 7 }, // 57
+ {"nasty", 11, "Algorithm: Nasty (Order: 11)", generate_nasty, 1.5,1., 8 }, // 58
+ {"free", 11, "Algorithm: Freeform/4 (Order: 11)", generate_freeform, 1.5,1., 9 }, // 59
+ {"rogue", 11, "Algorithm: Rogue (Order: 11)", generate_rogue, 1.6,1.,10 }, // 60
+ {"embed", 11, "Algorithm: Embed (Order: 11)", generate_embed, 4.,1.,10 }, // 61
+ {"shape", 10, "Mmmm... Doughnut", generate_shape, 1.,2.,10 }, // 62
+
+ {"dense", 12, "Algorithm: Original/Dense (Order: 12)", generate_dense, .8,1., 5 }, // 63
+ {"simple",12, "Algorithm: Original (Order: 12)", generate_simple, 1.,1., 6 }, // 64
+ {"sparse",12, "Algorithm: Original/Sparse (Order: 12)",generate_sparse, 1.2,1., 7 }, // 65
+ {"nasty", 12, "Algorithm: Nasty (Order: 12)", generate_nasty, 1.5,1., 8 }, // 66
+ {"free", 12, "Algorithm: Freeform/4 (Order: 12)", generate_freeform, 1.5,1., 9 }, // 67
+ {"rogue", 12, "Algorithm: Rogue (Order: 12)", generate_rogue, 1.6,1.,10 }, // 68
+ {"embed", 12, "Algorithm: Embed (Order: 12)", generate_embed, 4.,1.,10 }, // 69
+ {"shape", 11, "Quick and Dirty, or Slow and Steady", generate_shape, 1.,1.,10 }, // 70
+ {"shape", 5, "Little Fluffy Clouds", generate_shape, 1.,2., 6 }, // 29
+
+ {"dense", 13, "Algorithm: Original/Dense (Order: 13)", generate_dense, .8,1., 5 }, // 71
+ {"simple",13, "Algorithm: Original (Order: 13)", generate_simple, 1.,1., 6 }, // 72
+ {"sparse",13, "Algorithm: Original/Sparse (Order: 13)",generate_sparse, 1.2,1., 7 }, // 73
+ {"nasty", 13, "Algorithm: Nasty (Order: 13)", generate_nasty, 1.5,1., 8 }, // 74
+ {"free", 13, "Algorithm: Freeform/4 (Order: 13)", generate_freeform, 1.5,1., 9 }, // 75
+ {"rogue", 13, "Algorithm: Rogue (Order: 13)", generate_rogue, 1.6,1.,10 }, // 76
+ {"embed", 13, "Algorithm: Embed (Order: 13)", generate_embed, 4.,1.,10 }, // 77
+ {"shape", 12, "A Sudden Urge To Go Shopping", generate_shape, 1.,1.,10 }, // 78
+ {"shape", 13, "Sweet Reward", generate_shape, 1.,1.,10 }, // 79
+
};
-#define LOOP_LEVELS 7
+#define LOOP_LEVELS 8
static gen_instance i_list_loop[LOOP_LEVELS]={
- {"dense", 8, "Algorithm: Original/Dense (Order: %d)", generate_dense, .8,1., 5 }, // n
- {"simple", 8, "Algorithm: Original (Order: %d)", generate_simple, 1.,1., 5 }, // n
- {"sparse", 8, "Algorithm: Original/Sparse (Order: %d)",generate_sparse, 1.2,1., 5 }, // n
- {"nasty", 8, "Algorithm: Nasty (Order: %d)", generate_nasty, 1.5,1., 5 }, // n
- {"free", 8, "Algorithm: Freeform/4 (Order: %d)", generate_freeform, 1.5,1., 5 }, // n
- {"rogue", 8, "Algorithm: Rogue (Order: %d)", generate_rogue, 1.6,1., 5 }, // n
- {"embed", 8, "Algorithm: Embed (Order: %d)", generate_embed, 4.,1., 5 }, // n
+ {"dense", 14, "Algorithm: Original/Dense (Order: %d)", generate_dense, .8,1., 5 }, // n
+ {"simple",14, "Algorithm: Original (Order: %d)", generate_simple, 1.,1., 6 }, // n
+ {"sparse",14, "Algorithm: Original/Sparse (Order: %d)",generate_sparse, 1.2,1., 7 }, // n
+ {"nasty", 14, "Algorithm: Nasty (Order: %d)", generate_nasty, 1.5,1., 8 }, // n
+ {"free", 14, "Algorithm: Freeform/4 (Order: %d)", generate_freeform, 1.5,1., 9 }, // n
+ {"rogue", 14, "Algorithm: Rogue (Order: %d)", generate_rogue, 1.6,1.,10 }, // n
+ {"embed", 14, "Algorithm: Embed (Order: %d)", generate_embed, 4.,1.,10 }, // n
+ {"shape", 14, "Algorithm: Region (Order: %d)", generate_shape, 1.,2.,10 },
};
int generate_find_number(char *id){
Modified: trunk/planarity/graph_generate.h
===================================================================
--- trunk/planarity/graph_generate.h 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_generate.h 2005-10-14 12:22:47 UTC (rev 10156)
@@ -36,6 +36,7 @@
extern void generate_embed(graph *g, int order);
extern void generate_crest(graph *g, int order);
-extern void generate_freeform(graph *g, int order);
extern void generate_data(graph *g, int order);
+extern void generate_freeform(graph *g, int order);
+extern void generate_shape(graph *g, int order);
Modified: trunk/planarity/graph_generate_mesh1.c
===================================================================
--- trunk/planarity/graph_generate_mesh1.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_generate_mesh1.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -88,7 +88,7 @@
while(el){
edge *e = el->edge;
- if(intersects(A,B,e->A,e->B,&dummy_x,&dummy_y))
+ if(intersectsV(A,B,e->A,e->B,&dummy_x,&dummy_y))
return 1;
el=el->next;
@@ -556,7 +556,7 @@
int count=0;
while(e){
- if(intersects(A,B,e->A,e->B,&dummy_x,&dummy_y))
+ if(intersectsV(A,B,e->A,e->B,&dummy_x,&dummy_y))
count++;
e=e->next;
}
Modified: trunk/planarity/graph_generate_mesh2.c
===================================================================
--- trunk/planarity/graph_generate_mesh2.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_generate_mesh2.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -33,6 +33,7 @@
#include "gameboard.h"
#include "graph_generate.h"
#include "graph_arrange.h"
+#include "graph_region.h"
/* Mesh1 has three primary considerations in mind:
1) By default, act like the algorithm in the original planarity
@@ -51,29 +52,41 @@
} mesh;
// check for intersections with other edges
-static int check_intersects_edge(mesh *m, edge *e){
+static int check_intersects_edge(mesh *m, edge *e, int intersections){
edge *ge = m->g->edges;
+ int count=0;
+
while(ge){
double xo,yo;
- if(intersects(ge->A,ge->B,e->A,e->B,&xo,&yo))return 1;
+
+ // edges that share a vertex don't intersect by definition
+ if(ge->A!=e->A && ge->A!=e->B && ge->B!=e->A && ge->B!=e->B)
+ if(intersects(ge->A->orig_x,ge->A->orig_y,
+ ge->B->orig_x,ge->B->orig_y,
+ e->A->orig_x,e->A->orig_y,
+ e->B->orig_x,e->B->orig_y,
+ &xo,&yo)){
+ count++;
+ if(count>intersections)return 1;
+ }
ge=ge->next;
}
return 0;
}
static float dot(vertex *A, vertex *B, vertex *C){
- return (float)(B->x-A->x)*(float)(C->x-B->x) +
- (float)(B->y-A->y)*(float)(C->y-B->y);
+ return (float)(B->orig_x-A->orig_x)*(float)(C->orig_x-B->orig_x) +
+ (float)(B->orig_y-A->orig_y)*(float)(C->orig_y-B->orig_y);
}
static float cross(vertex *A, vertex *B, vertex *C){
- return (float)(B->x-A->x)*(float)(C->y-A->y) -
- (float)(B->y-A->y)*(float)(C->x-A->x);
+ return (float)(B->orig_x-A->orig_x)*(float)(C->orig_y-A->orig_y) -
+ (float)(B->orig_y-A->orig_y)*(float)(C->orig_x-A->orig_x);
}
static float sq_point_distance(vertex *A, vertex *B){
- float xd = A->x-B->x;
- float yd = A->y-B->y;
+ float xd = A->orig_x-B->orig_x;
+ float yd = A->orig_y-B->orig_y;
return xd*xd+yd*yd;
}
@@ -95,120 +108,247 @@
vertex *v = m->g->verticies;
while(v){
- if(v!=e->A && v!=e->B && sq_line_distance(e,v)<100)return 1;
+ if(v!=e->A && v!=e->B && sq_line_distance(e,v)<16)return 1;
v=v->next;
}
return 0;
}
-// Although very inefficient, it is simple and correct. Even
-// impossibly large boards generate in a fraction of a second on old
-// boxen. There's likely no need to bother optimizing this step of
-// board creation. */
-static void span_depth_first2(mesh *m,vertex *current, float length_limit){
+static int select_available(mesh *m,vertex *current,float length_limit,int intersections){
+ int count=0;
+ vertex *v = m->g->verticies;
- while(1){
- // Mark/count all possible choices
- int count=0;
- int count2=0;
- int choice;
- vertex *v = m->g->verticies;
-
- while(v){
- v->selected = 0;
- if(!v->edges && v!=current){
- if(sq_point_distance(v,current)<=length_limit){
+ // mark all possible choices
+ while(v){
+ v->selected = 0;
+ if(v!=current){
+ if(length_limit==0 || sq_point_distance(v,current)<=length_limit){
+ if(!exists_edge(v,current)){
edge e;
e.A = v;
e.B = current;
- if(!check_intersects_edge(m,&e)){
- if(!check_intersects_vertex(m,&e)){
- v->selected = 1;
- count++;
+ if(!region_intersects(&e)){
+ if(!check_intersects_edge(m,&e,intersections)){
+ if(!check_intersects_vertex(m,&e)){
+ v->selected=1;
+ count++;
+ }
}
}
}
}
- v=v->next;
}
+ v=v->next;
+ }
- if(count == 0) return;
-
- choice = random_number()%count;
- count2 = 0;
- v = m->g->verticies;
- while(v){
- if(v->selected){
- if(count2++ == choice){
- add_edge(m->g,v,current);
- span_depth_first2(m,v, length_limit);
- break;
- }
- }
- v=v->next;
+ return count;
+}
+
+// Although very inefficient, it is simple and correct. Even
+// impossibly large boards generate in a fraction of a second on old
+// boxen. There's likely no need to bother optimizing this step of
+// board creation. */
+
+typedef struct insort{
+ int metric;
+ vertex *v;
+} insort;
+
+static int insort_c(const void *a, const void *b){
+ insort *A=(insort *)a;
+ insort *B=(insort *)b;
+ return(A->metric-B->metric);
+}
+
+static vertex *vertex_num_sel(graph *g,int num){
+ vertex *v=g->verticies;
+ if(num<0)return 0;
+ while(v){
+ if(v->selected){
+ if(!num)
+ break;
+ else
+ num--;
}
-
- if(count == 1) return; // because we just took care of it
+ v=v->next;
}
+ return v;
}
-static void random_populate(mesh *m,vertex *current,int dense_128, float length_limit){
- int num_edges=0,count=0;
- edge_list *el=current->edges;
- vertex *v = m->g->verticies;
- while(el){
- num_edges++;
- el=el->next;
+static void prepopulate(mesh *m,int length_limit){
+ // sort all verticies in ascending order by their number of potential edges
+ int i=0;
+ insort index[m->g->vertex_num];
+ vertex *v=m->g->verticies;
+
+ while(v){
+ index[i].v=v;
+ index[i].metric = select_available(m,v,0,0);
+ i++;
+ v=v->next;
}
+ qsort(index,m->g->vertex_num,sizeof(*index),insort_c);
- // mark all possible choices
- while(v){
- v->selected = 0;
- if(v!=current){
- if(sq_point_distance(v,current)<=length_limit){
- if(!exists_edge(v,current)){
- edge e;
- e.A = v;
- e.B = current;
- if(!check_intersects_edge(m,&e)){
- if(!check_intersects_vertex(m,&e)){
- v->selected=1;
- count++;
+ // populate in ascending order
+ for(i=0;i<m->g->vertex_num;i++){
+ int intersections=0;
+ int edges=0;
+ v = index[i].v;
+
+ // does this vertex already have edges?
+ {
+ edge_list *el=v->edges;
+ while(el){
+ edges++;
+ el=el->next;
+ if(edges>=2)break;
+ }
+ }
+ if(edges>=2)continue;
+
+ // it's possible some intersections will be necessary, but go for
+ // fewest possible
+ while(edges<2 && intersections<10){
+ int count = select_available(m,v,length_limit,intersections);
+ if(count){
+ vertex *short0=0;
+ vertex *short1=0;
+ vertex *w=m->g->verticies;
+ long d0;
+ long d1;
+
+ if(length_limit){
+ // choose two at random
+ int a=random_number()%count;
+ int b=-1;
+
+ if(count>1)
+ while(b==-1){
+ b=random_number()%count;
+ if(b==a)b=-1;
}
+
+ short0=vertex_num_sel(m->g,a);
+ short1=vertex_num_sel(m->g,b);
+
+ }else{
+ // used with region-constrined meshes
+ // of the possible edges, choose the shortest two
+ while(w){
+ if(w!=v && w->selected){
+ int xd=w->orig_x-v->orig_x;
+ int yd=w->orig_y-v->orig_y;
+ long d=xd*xd+yd*yd;
+ if(!short0){
+ short0=w;
+ d0=d;
+ }else if(!short1 || d<d1){
+ if(d<d0){
+ short1=short0;
+ d1=d0;
+ short0=w;
+ d0=d;
+ }else{
+ short1=w;
+ d1=d;
+ }
+ }
+ }
+ w=w->next;
}
}
+
+ if(short0){
+ add_edge(m->g,v,short0);
+ edges++;
+ m->g->objective +=intersections;
+ if(intersections)m->g->objective_lessthan=1;
+ }
+ if(edges<2 && short1){
+ add_edge(m->g,v,short1);
+ edges++;
+ m->g->objective +=intersections;
+ if(intersections)m->g->objective_lessthan=1;
+ }
}
+ intersections++;
}
- v=v->next;
}
+}
- // make sure no vertex is a leaf
- if(num_edges<2){
- int choice = random_number() % count;
- count = 0;
-
- v = m->g->verticies;
- while(v){
- if(v->selected){
- if(count++ == choice){
- add_edge(m->g,v,current);
- v->selected=0;
- break;
+// the spanning walk is to make an attempt at a single, connected graph.
+static void span_depth_first2(mesh *m,vertex *current, float length_limit){
+
+ current->grabbed=1; // overloaded; "we walked this already"
+ while(1){
+ // prefer walking along edges that already exist
+ {
+ edge_list *el=current->edges;
+
+ while(el){
+ edge *e=el->edge;
+ vertex *v;
+ if(e->A==current)
+ v=e->B;
+ else
+ v=e->A;
+
+ if(!v->grabbed){
+ span_depth_first2(m, v, length_limit);
}
+
+ el=el->next;
}
- v=v->next;
}
+
+ // now walk any possible edges that have not been walked
+ {
+ int count=select_available(m,current,length_limit,0);
+ int count2=0;
+ int choice;
+ vertex *v = m->g->verticies;
+
+ // filter out already-walked edges
+ while(v){
+ if(v->grabbed && v->selected){ // grabbed is also overloaded to mean not walked
+ v->selected = 0;
+ count--;
+ }
+ v=v->next;
+ }
+
+ if(count == 0) return;
+
+ choice = random_number()%count;
+ v = m->g->verticies;
+ while(v){
+ if(v->selected){
+ if(count2++ == choice){
+ add_edge(m->g,v,current);
+ span_depth_first2(m,v, length_limit);
+ break;
+ }
+ }
+ v=v->next;
+ }
+
+ if(count == 1) return; // because we just took care of it
+ }
}
+}
- // now, random populate
- v = m->g->verticies;
- while(v){
- if(v->selected && random_yes(dense_128)){
- add_edge(m->g,v,current);
- v->selected=0;
+static void random_populate(mesh *m,vertex *current,int dense_128, float length_limit){
+ int count=select_available(m,current,length_limit,0);
+ if(count){
+ vertex *v = m->g->verticies;
+ while(v){
+ if(v->selected && random_yes(dense_128)){
+ add_edge(m->g,v,current);
+ v->selected=0;
+ }
+ v=v->next;
}
- v=v->next;
}
}
@@ -269,6 +409,7 @@
}
new_board(g, m->width * m->height);
+ region_init(); // clear it
// used for intersection calcs
{
@@ -276,8 +417,8 @@
vertex *v = g->verticies;
for(y=0;y<m->height;y++)
for(x=0;x<m->width;x++){
- v->x=x*50; // not a random number
- v->y=y*50; // not a random number
+ v->orig_x=x*50; // not a random number
+ v->orig_y=y*50; // not a random number
v=v->next;
}
}
@@ -292,16 +433,42 @@
length_limit*=50;
length_limit*=length_limit;
-
- /* first walk a random spanning tree */
- span_depth_first2(m, m->g->verticies, length_limit);
-
+
+ if(have_region())
+ prepopulate(m,0);
+
+ /* connect the graph into as few discrete sections as possible */
+ v = m->g->verticies;
+ while(v){
+ v->grabbed = 0;
+ v=v->next;
+ }
+
+ v = m->g->verticies;
+ // make sure we walk all verticies
+ while(v){
+ if(!v->grabbed)
+ span_depth_first2(m, m->g->verticies, length_limit);
+ v=v->next;
+ }
+
+ if(!have_region())
+ prepopulate(m,length_limit);
+
/* now iterate the whole mesh adding random edges */
v=m->g->verticies;
while(v){
random_populate(m, v, density_128, length_limit);
v=v->next;
}
+
+ /* clear out overloaded flags */
+ v=m->g->verticies;
+ while(v){
+ v->grabbed=0;
+ v=v->next;
+ }
+
deselect_verticies(m->g);
}
@@ -310,12 +477,94 @@
random_seed(order+1);
mesh_setup(g, &m, order, 0);
- generate_mesh2(&m,48,5);
- //arrange_verticies_mesh(g,m.width,m.height);
+ generate_mesh2(&m,48,4);
randomize_verticies(g);
if(order*.03<.3)
arrange_verticies_polycircle(g,4,0,order*.03,0,0,0);
else
arrange_verticies_polycircle(g,4,0,.3,0,0,0);
+
}
+
+void generate_shape(graph *g, int order){
+ int mod=0;
+ int dens=64;
+ int min=8;
+ mesh m;
+ random_seed(order+1);
+
+ switch(order%13){
+ case 0: // star
+ mod=10; break;
+ case 1:
+ break;
+ case 2: // dashed circle
+ dens=48; break;
+ case 3: // bifur
+ dens=80; break;
+ case 4:
+ break;
+ case 5:
+ min = 12;
+ dens = 10;
+ break;
+ case 6:
+ min = 10;
+ break;
+ case 7:
+ min = 10;
+ break;
+ case 8:
+ min = 10;
+ break;
+ case 9:
+ min = 10;
+ break;
+ case 10: // ring
+ dens=128;
+ min = 11;
+ break;
+ case 11:
+ min = 12;
+ break;
+ case 12: // target
+ dens=128;
+ min = 14;
+ break;
+ }
+
+ mesh_setup(g, &m, (order>min?order:min), mod);
+ randomize_verticies(g);
+
+ switch(order % 13){
+ case 0: // star
+ arrange_region_star(g); break; //4
+ case 1: // rainbow
+ arrange_region_rainbow(g); break; //9
+ case 2: // dashed circle
+ arrange_region_dashed_circle(g); break; //0
+ case 3: // bifur
+ arrange_region_bifur(g); break; //0
+ case 4: // dairyqueen
+ arrange_region_dairyqueen(g); break; //0
+ case 5: // cloud
+ arrange_region_cloud(g); break; //0
+ case 6: // storm
+ arrange_region_storm(g); break; //11
+ case 7: // plus;
+ arrange_region_plus(g); break; //2
+ case 8:
+ arrange_region_hole3(g); break; //4
+ case 9:
+ arrange_region_hole4(g); break; //15
+ case 10: // ring
+ arrange_region_ring(g); break; //29
+ case 11:
+ arrange_region_ovals(g); break; //95
+ case 12: // target
+ arrange_region_target(g); break; //108
+ }
+
+ generate_mesh2(&m,dens,0);
+}
Added: trunk/planarity/graph_region.c
===================================================================
--- trunk/planarity/graph_region.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_region.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -0,0 +1,830 @@
+/*
+ *
+ * gPlanarity:
+ * The geeky little puzzle game with a big noodly crunch!
+ *
+ * gPlanarity copyright (C) 2005 Monty <monty at xiph.org>
+ * Original Flash game by John Tantalo <john.tantalo at case.edu>
+ * Original game concept by Mary Radcliffe
+ *
+ * gPlanarity is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * gPlanarity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Postfish; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "graph.h"
+#include "graph_region.h"
+
+/* Regions are 'electric fences' for mesh building; used in mesh2 to
+ make non-convex shapes */
+
+typedef struct region_segment {
+ int layout; /* 0 no layout, 1 left, 2 right, 3 layout-only */
+ int cont; /* is this continuous from last line? */
+
+ float x1;
+ float y1;
+ float x2;
+ float y2;
+
+ // arc computation cache (if arc)
+ float cx;
+ float cy;
+ float radius;
+ float phi0;
+ float phi1;
+ float phi;
+
+ float length;
+ struct region_segment *next;
+} region_segment;
+
+typedef struct region{
+ int num;
+ region_segment *l;
+
+ int ox,oy,x,y;
+ int layout;
+
+ int cont;
+} region;
+
+static region r;
+static region layout_adj;
+static region_segment *segpool=0;
+
+#define CHUNK 64
+
+static region_segment *new_segment(region *r, int x1,int y1,int x2, int y2){
+ region_segment *ret;
+
+ if(!segpool){
+ int i;
+ segpool = calloc(CHUNK,sizeof(*segpool));
+ for(i=0;i<CHUNK-1;i++) /* last addition's next points to nothing */
+ segpool[i].next=segpool+i+1;
+ }
+
+ ret=segpool;
+ segpool=ret->next;
+
+ memset(ret,0,sizeof(*ret));
+ ret->next = r->l;
+ ret->layout=r->layout;
+ ret->x1=x1;
+ ret->y1=y1;
+ ret->x2=x2;
+ ret->y2=y2;
+ ret->cont = r->cont;
+
+ r->l=ret;
+
+ return ret;
+}
+
+/* angle convention: reversed y (1,-1 is first quadrant, ala X
+ windows), range -PI to PI */
+
+static int intersects_arc(edge *e, region_segment *r){
+ float Ax = e->A->x - r->cx;
+ float Ay = e->A->y - r->cy;
+ float Bx = e->B->x - r->cx;
+ float By = e->B->y - r->cy;
+
+ float dx = Bx - Ax;
+ float dy = By - Ay;
+ float dr2 = dx*dx + dy*dy;
+ float D = Ax*By - Bx*Ay;
+ float discriminant =(r->radius*r->radius)*dr2 - D*D;
+
+ // does it even intersect the full circle?
+ if(discriminant<=0)return 0;
+
+ {
+ float x1,y1,x2,y2;
+
+ float sqrtd = sqrt(discriminant);
+ float sign = (dy>0?1.f:-1.f);
+
+ // finite precision required here else 0/inf slope lines will be
+ // slighly off the secant
+ x1 = rint((D*dy + sign*dx*sqrtd) / dr2);
+ x2 = rint((D*dy - sign*dx*sqrtd) / dr2);
+
+ y1 = rint((-D*dx + fabs(dy)*sqrtd) / dr2);
+ y2 = rint((-D*dx - fabs(dy)*sqrtd) / dr2);
+
+ Ax = rint(Ax);
+ Ay = rint(Ay);
+ Bx = rint(Bx);
+ By = rint(By);
+
+ // is x1,y1 actually on the segment?
+ if( !(x1<Ax && x1<Bx) &&
+ !(x1>Ax && x1>Bx) &&
+ !(y1<Ay && y1<By) &&
+ !(y1>Ay && y1>By)){
+ // yes. it is in the angle range we care about?
+
+ float ang = acos(x1 / r->radius);
+ if(y1>0) ang = -ang;
+
+ if(r->phi<0){
+ if(r->phi0 < r->phi1){
+ if(ang <= r->phi0 || ang >= r->phi1)return 1;
+ }else{
+ if(ang <= r->phi0 && ang >= r->phi1)return 1;
+ }
+ }else{
+ if(r->phi0 < r->phi1){
+ if(ang >= r->phi0 && ang <= r->phi1)return 1;
+ }else{
+ if(ang >= r->phi0 || ang <= r->phi1)return 1;
+ }
+ }
+ }
+
+ // is x2,y2 actually on the segment?
+ // if so, it is in the arc range we care about?
+ if( !(x2<Ax && x2<Bx) &&
+ !(x2>Ax && x2>Bx) &&
+ !(y2<Ay && y2<By) &&
+ !(y2>Ay && y2>By)){
+ // yes. it is in the angle range we care about?
+
+ float ang = acos(x2 / r->radius);
+ if(y2>0) ang = -ang;
+
+ if(r->phi<0){
+ if(r->phi0 < r->phi1){
+ if(ang <= r->phi0 || ang >= r->phi1)return 1;
+ }else{
+ if(ang <= r->phi0 && ang >= r->phi1)return 1;
+ }
+ }else{
+ if(r->phi0 < r->phi1){
+ if(ang >= r->phi0 && ang <= r->phi1)return 1;
+ }else{
+ if(ang >= r->phi0 || ang <= r->phi1)return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static float line_angle(float x1, float y1, float x2, float y2){
+ float xd = x2-x1;
+ float yd = y2-y1;
+
+ if(xd == 0){
+ if(yd>0)
+ return -M_PI/2;
+ else
+ return M_PI/2;
+ }else if(xd<0){
+ if(yd<0)
+ return atan(-yd/xd)+M_PI;
+ else
+ return atan(-yd/xd)-M_PI;
+ }else{
+ return atan(-yd/xd);
+ }
+}
+
+static float line_mag(float x1, float y1, float x2, float y2){
+ float xd = x2-x1;
+ float yd = y2-y1;
+ return hypot(xd,yd);
+}
+
+static void compute_arc(region_segment *r,float phi){
+ float x1=r->x1;
+ float y1=r->y1;
+ float x2=r->x2;
+ float y2=r->y2;
+ float ar,br,cr;
+ float cx,cy,a,c,d;
+ float xd = x2-x1;
+ float yd = y2-y1;
+
+ if(phi<-M_PI){
+ ar = phi + M_PI*2;
+ }else if (phi<0){
+ ar = -phi;
+ }else if (phi<M_PI){
+ ar = phi;
+ }else{
+ ar = M_PI*2 - phi;
+ }
+
+ cr = line_angle(x1,y1,x2,y2);
+ a = line_mag(x1,y1,x2,y2)/2.f;
+ br=(M_PI/2.f)-(ar/2.f);
+ c = tan(br)*a;
+ d = hypot(a,c);
+
+ if(phi<-M_PI || (phi>0 && phi<M_PI)){
+ cx = x1 + cos(cr+M_PI/2)*c + xd/2;
+ cy = y1 - sin(cr+M_PI/2)*c + yd/2;
+ }else{
+ cx = x1 + cos(cr-M_PI/2)*c + xd/2;
+ cy = y1 - sin(cr-M_PI/2)*c + yd/2;
+ }
+
+ r->cx=cx;
+ r->cy=cy;
+ r->radius=d;
+
+ // have the center of the circle, have radius. Determine the
+ // portion of the arc we want.
+ r->phi0 = acos( (x1-cx) / d);
+ r->phi1 = acos( (x2-cx) / d);
+ if(y1>cy) r->phi0= -r->phi0;
+ if(y2>cy) r->phi1= -r->phi1;
+ r->phi=phi;
+}
+
+static region_segment *region_arc(region *re, int x1, int y1, int x2, int y2, float rad){
+ region_segment *n= new_segment(re,x1,y1,x2,y2);
+ compute_arc(n,rad);
+ return n;
+}
+
+static region_segment *region_line(region *re,int x1, int y1, int x2, int y2){
+ return new_segment(re,x1,y1,x2,y2);
+}
+
+/* The overall idea here is to massage the region segments and arcs
+ slightly so that when we layout points based on a region, the
+ layout is slightly inside or outside (as requested) the actual
+ region. This also reverses the path when rebuilding into the new
+ region, putting it in the order we actually need to evaluate it in.
+*/
+
+#define ADJ 2.f
+
+static void point_adj(float x1, float y1, float x2, float y2, float *Px, float *Py, int left){
+ float xd = x2-x1;
+ float yd = y2-y1;
+ float M = hypot(xd,yd);
+
+ if(left){
+ *Px += yd/M*ADJ;
+ *Py += -xd/M*ADJ;
+ }else{
+ *Px += -yd/M*ADJ;
+ *Py += xd/M*ADJ;
+ }
+}
+
+static void line_adj(float *x1, float *y1, float *x2, float *y2, int left){
+ float xd = *x2-*x1;
+ float yd = *y2-*y1;
+ float M = hypot(xd,yd);
+
+ if(left){
+ *x1 += yd/M*ADJ;
+ *x2 += yd/M*ADJ;
+ *y1 += -xd/M*ADJ;
+ *y2 += -xd/M*ADJ;
+ }else{
+ *x1 += -yd/M*ADJ;
+ *x2 += -yd/M*ADJ;
+ *y1 += xd/M*ADJ;
+ *y2 += xd/M*ADJ;
+ }
+
+ // make sure there's an overlap!
+ *x1-=xd/M*4.;
+ *x2+=xd/M*4.;
+ *y1-=yd/M*4.;
+ *y2+=yd/M*4.;
+}
+
+
+static float tangent_distance_from_center(float x1, float y1, float x2, float y2,
+ float cx, float cy){
+ float xd = x2 - x1;
+ float yd = y2 - y1;
+ return ((x2-x1)*(cy-y1) - (y2-y1)*(cx-x1)) / hypot(xd,yd);
+}
+
+static float radius_adjust(float r, float arc_phi, int left){
+ if(arc_phi<0){
+ if(left){
+ r+=ADJ;
+ }else{
+ r-=ADJ;
+ }
+ }else{
+ if(left){
+ r-=ADJ;
+ }else{
+ r+=ADJ;
+ }
+ }
+ return r;
+}
+
+static void line_line_adj(region_segment *A, region_segment *B,
+ float *new_x, float *new_y, int left){
+ double newd_x;
+ double newd_y;
+
+ float Ax1=A->x1;
+ float Ay1=A->y1;
+ float Ax2=A->x2;
+ float Ay2=A->y2;
+
+ float Bx1=B->x1;
+ float By1=B->y1;
+ float Bx2=B->x2;
+ float By2=B->y2;
+
+ line_adj(&Ax1, &Ay1, &Ax2, &Ay2, left);
+ line_adj(&Bx1, &By1, &Bx2, &By2, left);
+
+ // compute new intersection
+ if(!intersects(Ax1,Ay1,Ax2,Ay2, Bx1,By1,Bx2,By2, &newd_x, &newd_y)){
+ // odd; do nothing rather than fail unpredictably
+ *new_x=Ax2;
+ *new_y=Ay2;
+ }else{
+ *new_x=newd_x;
+ *new_y=newd_y;
+ }
+}
+
+static void line_arc_adj(float x1, float y1, float x2, float y2,
+ float cx, float cy, float r, float arc_phi,
+ float *new_x2, float *new_y2, int lleft, int aleft){
+ float xd = x2 - x1;
+ float yd = y2 - y1;
+ float c = tangent_distance_from_center(x1,y1,x2,y2,cx,cy);
+ float a = sqrt(r*r - c*c),a2;
+ float M = hypot(xd,yd);
+ float ax = x2 + xd/M*a;
+ float ay = y2 + yd/M*a;
+
+ float ax1 = x2 - xd/M*a;
+ float ay1 = y2 - yd/M*a;
+ if(hypot(ax1-cx,ay1-cy) < hypot(ax-cx,ay-cy)){
+ ax=ax1;
+ ay=ay1;
+ }
+
+ xd = ax-x2;
+ yd = ay-y2;
+
+ point_adj(x1, y1, x2, y2, &ax, &ay, lleft);
+
+ r = radius_adjust(r,arc_phi,aleft);
+ c = hypot(cx-ax,cy-ay);
+ a2 = sqrt(r*r-c*c);
+
+ *new_x2 = ax - xd/a*a2;
+ *new_y2 = ay - yd/a*a2;
+}
+
+static void arc_arc_adj(region_segment *arc, region_segment *next,
+ float *new_x2, float *new_y2, int left){
+ float x2 =arc->x2;
+ float y2 =arc->y2;
+
+ float cx1=arc->cx;
+ float cy1=arc->cy;
+ float r1 =arc->radius;
+
+ float cx2=next->cx;
+ float cy2=next->cy;
+ float r2 =next->radius;
+
+ float c;
+ float xd = cx2-cx1;
+ float yd = cy2-cy1;
+ float d = hypot(xd,yd);
+ float x = (d*d - r1*r1 + r2*r2) / (2*d);
+
+ // is the old x2/y2 to the left or right of the line connecting the
+ // circle centers?
+ float angle_x2y2 = line_angle(cx1,cy1,x2,y2);
+ float angle_c1c2 = line_angle(cx1,cy1,cx2,cy2);
+ float angle = angle_x2y2 - angle_c1c2;
+ if(angle < -M_PI)angle += M_PI*2.f;
+ if(angle > M_PI)angle -= M_PI*2.f;
+
+ r1=radius_adjust(r1,arc->phi,left);
+ r2=radius_adjust(r2,arc->phi,left);
+
+ if(r1+r2>=d){
+ // still have a valid solution
+ x = (d*d - r1*r1 + r2*r2) / (2*d);
+ c = sqrt(r2*r2 - x*x);
+
+ if(angle>0){
+ // left of c1,c2 segment
+ *new_x2 = cx1+xd/d*x + yd/d*c;
+ *new_y2 = cy1+yd/d*x - xd/d*c;
+ }else{
+ // right
+ *new_x2 = cx1+xd/d*x - yd/d*c;
+ *new_y2 = cy1+yd/d*x + xd/d*c;
+ }
+ }else{
+ // circles shrunk and no longer overlap.
+ fprintf(stderr,"region overlap adjustment failed in arc_arc_adj; \n"
+ " This is an internal error that should never happen.\n");
+ }
+}
+
+static float phisub(float phi0, float phi1, float arcphi){
+ float phid = phi1-phi0;
+ if(arcphi<0){
+ if(phid>0) phid -= M_PI*2.f;
+ }else{
+ if(phid<0) phid += M_PI*2.f;
+ }
+ return phid;
+}
+
+static void radius_adj_xy(region_segment *s,float *x1,float *y1, int left){
+ float xd = *x1 - s->cx;
+ float yd = *y1 - s->cy;
+
+ float r = s->radius;
+ float new_r = radius_adjust(r,s->phi,left);
+ float delta = new_r/r;
+
+ *x1 = s->cx + xd*delta;
+ *y1 = s->cy + yd*delta;
+}
+
+static void adjust_layout(){
+ /* build adjustments from intersection region into layout region */
+ region_segment *s = r.l;
+ region_segment *endpath = 0;
+ region_segment *endpath_adj = 0;
+ float x2=-1,y2=-1;
+
+ // first, release previous layout
+ region_segment *l=layout_adj.l;
+ region_segment *le=l;
+
+ while(le && le->next)le=le->next;
+ if(le){
+ le->next=segpool;
+ segpool=l;
+ }
+ memset(&layout_adj,0,sizeof(layout_adj));
+
+ while(s){
+ float x1=0,y1=0,phi=0,radius=0;
+
+ if(s->cont){
+ if(!endpath){
+ endpath=s;
+ endpath_adj=0;
+ }
+ }
+
+ if(s->layout){
+ if(s->layout<3){
+
+ // the flags mark beginning and end of the path, but don't say
+ // if it's closed.
+ if(!s->cont && endpath_adj)
+ if(endpath->x2 != s->x1 ||
+ endpath->y2 != s->y1)
+ endpath_adj=0;
+
+ /* first handle the lone-circle special case */
+ if(s->x1==s->x2 && s->y1==s->y2){
+ if(s->radius>0){
+ if(s->layout == 1) radius= s->radius+2;
+ if(s->layout == 2) radius= s->radius-2;
+ x1=x2=s->x1;y1=y2=s->y1;
+ phi=s->phi;
+ }
+ }else{
+ region_segment *p = 0;
+
+ if(s->cont)
+ p = s->next;
+ else if(endpath_adj)
+ p = endpath;
+
+ if(p){
+ if(s->radius){
+ if(x2==-1){
+ x2=s->x2;
+ y2=s->y2;
+ radius_adj_xy(s,&x2,&y2,s->layout==1);
+ }
+ if(p->radius){
+ // arc - arc case
+ float phi0,phi1;
+ arc_arc_adj(p,s,&x1,&y1,s->layout==1);
+ phi0=line_angle(s->cx,s->cy,x1,y1);
+ phi1=line_angle(s->cx,s->cy,x2,y2);
+ phi=phisub(phi0,phi1,s->phi);
+ }else{
+ // arc-line case
+ float phi0,phi1;
+ line_arc_adj(p->x1, p->y1, p->x2, p->y2,
+ s->cx, s->cy, s->radius, s->phi,
+ &x1, &y1, s->layout==1, s->layout==1);
+ phi0=line_angle(s->cx,s->cy,x1,y1);
+ phi1=line_angle(s->cx,s->cy,x2,y2);
+ phi=phisub(phi0,phi1,s->phi);
+ }
+ }else{
+ if(x2==-1){
+ x2=s->x2;
+ y2=s->y2;
+ point_adj(s->x1, s->y1, s->x2, s->y2, &x2, &y2, s->layout==1);
+ }
+ if(p->radius){
+ // line-arc case
+ line_arc_adj(s->x2, s->y2, s->x1, s->y1,
+ p->cx, p->cy, p->radius, p->phi,
+ &x1, &y1, s->layout==2, s->layout==1);
+ }else{
+ // line-line case
+ line_line_adj(p, s, &x1, &y1, s->layout==1);
+ }
+ }
+ }else{
+ x1=s->x1;
+ y1=s->y1;
+ x2=s->x2;
+ y2=s->y2;
+ if(s->radius){
+ // lone arc case; alter radius
+ radius_adj_xy(s,&x1,&y1,s->layout==1);
+ radius_adj_xy(s,&x2,&y2,s->layout==1);
+ phi=s->phi;
+ }else{
+ // lone line segment case; offset
+ point_adj(s->x1, s->y1, s->x2, s->y2, &x1, &y1, s->layout==1);
+ point_adj(s->x1, s->y1, s->x2, s->y2, &x2, &y2, s->layout==1);
+
+ }
+ }
+ }
+ }else{
+ x1=s->x1;
+ x2=s->x2;
+ y1=s->y1;
+ y2=s->y2;
+ phi=s->phi;
+ if(x1==x2 && y1==y2)
+ radius = s->radius;
+ }
+
+ // push the region segment
+ {
+ region_segment *n=new_segment(&layout_adj,rint(x1),rint(y1),rint(x2),rint(y2));
+ n->layout=3;
+ n->cont=(s->cont || endpath_adj);
+
+ if(radius){
+ // circle; radius variable is treated as a flag
+ n->cx=x1;
+ n->cy=y1;
+ n->radius=radius;
+ n->phi0=-M_PI;
+ n->phi1= M_PI;
+ n->cont=1;
+ }else if(s->radius){
+ // arc
+ compute_arc(n,phi);
+ }
+ if(s->cont && !endpath_adj)endpath_adj=n;
+
+ }
+
+ if(endpath_adj && !s->cont){
+ // go back and clean up the endpath path member
+ endpath_adj->x2 = rint(x1);
+ endpath_adj->y2 = rint(y1);
+
+ if(endpath->radius>0){
+ endpath_adj->phi1=line_angle(endpath->cx,endpath->cy,endpath_adj->x2,endpath_adj->y2);
+ endpath_adj->phi=phisub(endpath_adj->phi0,endpath_adj->phi1,endpath_adj->phi);
+ }
+ }
+ }
+
+ if(!s->cont){
+ endpath_adj=0;
+ endpath=0;
+ x2=-1;
+ y2=-1;
+ }else{
+ x2=x1;
+ y2=y1;
+ }
+
+ s=s->next;
+ }
+}
+
+void region_init(){
+ // release any lines and arcs
+ region_segment *l=r.l;
+ region_segment *le=r.l;
+ region_segment *a=layout_adj.l;
+ region_segment *ae=layout_adj.l;
+
+ while(le && le->next)le=le->next;
+ while(ae && ae->next)ae=ae->next;
+
+ if(le){
+ le->next=segpool;
+ segpool=l;
+ }
+ if(ae){
+ ae->next=segpool;
+ segpool=a;
+ }
+
+ memset(&r,0,sizeof(r));
+ memset(&layout_adj,0,sizeof(layout_adj));
+}
+
+void region_layout(graph *g){
+ // count up the total length of the region segments used in layout
+ float length=0,acc=0,ldel;
+ int num_adj=g->vertex_num;
+ region_segment *l;
+ vertex *v = g->verticies;
+
+ adjust_layout();
+
+ l = layout_adj.l;
+
+ while(l){
+ if(l->radius==0){
+ float xd=l->x2 - l->x1;
+ float yd=l->y2 - l->y1;
+ length += l->length = hypot(xd,yd);
+ }else{
+ float diam = l->radius*2.f*M_PI;
+ float del=phisub(l->phi0,l->phi1,l->phi);
+ if(l->phi<0)
+ del = -del;
+
+ length += l->length = diam*del*(1.f/(M_PI*2.f));
+ }
+ l=l->next;
+ }
+
+ // non-contiguous beginnings sink a single point segment per
+ l = layout_adj.l;
+ while(l){
+ if(!l->cont)
+ num_adj--;
+ l=l->next;
+ }
+
+ /* perform layout segment by segment */
+ l = layout_adj.l;
+ ldel = (float)length/num_adj;
+ while(l && v){
+ int i;
+ int num_placed = l->cont ? rint((l->length-acc)/ldel) : rint((l->length-acc)/ldel)+1;
+ float snap_del = l->cont ? l->length/num_placed : l->length/(num_placed-1);
+ float snap_acc=l->cont?snap_del:0;
+
+ if(l->radius==0){
+ float x1 = l->x1;
+ float y1 = l->y1;
+ float x2 = l->x2;
+ float y2 = l->y2;
+ float xd=(x2-x1)/l->length;
+ float yd=(y2-y1)/l->length;
+
+ for(i=0;v && i<num_placed;i++){
+ v->x = rint(x1+xd*snap_acc);
+ v->y = rint(y1+yd*snap_acc);
+
+ if(snap_acc)
+ acc+=ldel;
+ snap_acc+=snap_del;
+ v=v->next;
+ }
+ }else{
+ /* next is an arc */
+ float x = l->cx;
+ float y = l->cy;
+ float phid = phisub(l->phi0,l->phi1,l->phi);
+
+ phid /= l->length;
+
+ for(i=0;v && i<num_placed;i++){
+ v->x = rint( cos(l->phi0+phid*snap_acc)*(l->radius)+x);
+ v->y = rint( -sin(l->phi0+phid*snap_acc)*(l->radius)+y);
+
+ if(snap_acc)
+ acc+=ldel;
+ snap_acc+=snap_del;
+ v=v->next;
+ }
+ }
+
+ acc-=l->length;
+ l=l->next;
+ }
+}
+
+void region_circle(int x,int y, float rad, int layout){
+ region_segment *a=new_segment(&r,0,0,0,0);
+ a->cx=a->x1=a->x2=x;
+ a->cy=a->y1=a->y2=y;
+ a->radius=rad;
+ a->phi0=-M_PI;
+ a->phi1=M_PI;
+ a->phi=M_PI*2.f;
+ a->layout=layout;
+ a->cont=0; // not really necessary, just consistent
+ r.cont=0;
+}
+
+void region_new_area(int x, int y, int layout){
+ r.x=r.ox=x;
+ r.y=r.oy=y;
+ r.layout=layout;
+ r.cont=0;
+}
+
+void region_line_to(int x,int y){
+ region_line(&r,r.x,r.y,x,y);
+ r.x=x;
+ r.y=y;
+ r.cont=1;
+}
+
+void region_arc_to(int x,int y, float rad){
+ region_arc(&r,r.x,r.y,x,y,rad);
+ r.x=x;
+ r.y=y;
+ r.cont=1;
+}
+
+void region_close_line(){
+ region_line(&r,r.x,r.y,r.ox,r.oy);
+ r.x=r.ox;
+ r.y=r.oy;
+ r.cont=0;
+}
+
+void region_close_arc(float rad){
+ region_arc(&r,r.x,r.y,r.ox,r.oy,rad);
+ r.x=r.ox;
+ r.y=r.oy;
+ r.cont=0;
+}
+
+int region_intersects(edge *e){
+
+ region_segment *s=r.l;
+ while(s){
+ if(s->layout<3){
+ if(s->radius!=0){
+ if(intersects_arc(e,s))return 1;
+ }else{
+ double xdummy,ydummy;
+
+ if(intersects(e->A->x,e->A->y,e->B->x,e->B->y,
+ s->x1,s->y1,s->x2,s->y2,
+ &xdummy,&ydummy))return 1;
+
+ }
+ }
+ s=s->next;
+ }
+ return 0;
+}
+
+int have_region(){
+ if(r.l)return 1;
+ return 0;
+}
Added: trunk/planarity/graph_region.h
===================================================================
--- trunk/planarity/graph_region.h 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_region.h 2005-10-14 12:22:47 UTC (rev 10156)
@@ -0,0 +1,37 @@
+/*
+ *
+ * gPlanarity:
+ * The geeky little puzzle game with a big noodly crunch!
+ *
+ * gPlanarity copyright (C) 2005 Monty <monty at xiph.org>
+ * Original Flash game by John Tantalo <john.tantalo at case.edu>
+ * Original game concept by Mary Radcliffe
+ *
+ * gPlanarity is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * gPlanarity 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Postfish; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+extern void region_init();
+
+extern int region_intersects(edge *e);
+extern void region_layout(graph *g);
+extern void region_circle(int x,int y, float rad, int layout);
+extern void region_new_area(int x, int y, int layout);
+extern void region_line_to(int x,int y);
+extern void region_arc_to(int x,int y, float rad);
+extern void region_close_line();
+extern void region_close_arc(float rad);
+extern int have_region();
Modified: trunk/planarity/graph_score.c
===================================================================
--- trunk/planarity/graph_score.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/graph_score.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -38,25 +38,25 @@
g->intersection_mult);
}
-int graphscore_get_multiplier(graph *g){
- float obj_multiplier = 1;
+int graphscore_get_multiplier_percent(graph *g){
+ float obj_multiplier = 100;
if(g->objective_lessthan)
if(g->objective > g->active_intersections)
- obj_multiplier += (g->objective-g->active_intersections)*g->objective_mult;
-
- return ceil( obj_multiplier );
+ obj_multiplier += 100.f * g->objective_mult / g->objective * (g->objective - g->active_intersections);
+
+ return ceil(obj_multiplier);
}
int graphscore_get_score(graph *g){
- return graphscore_get_raw_score(g)*graphscore_get_multiplier(g);
+ return graphscore_get_raw_score(g)*graphscore_get_multiplier_percent(g)/100;
}
int graphscore_get_bonus(graph *g){
- float obj_multiplier = graphscore_get_multiplier(g);
+ int obj_multiplier = graphscore_get_multiplier_percent(g);
if(get_timer()< g->original_intersections*g->intersection_mult)
- return ceil ((g->original_intersections*g->intersection_mult-get_timer()) * obj_multiplier);
+ return ceil ((g->original_intersections*g->intersection_mult-get_timer()) * obj_multiplier / 100);
return 0;
}
Modified: trunk/planarity/main.c
===================================================================
--- trunk/planarity/main.c 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/main.c 2005-10-14 12:22:47 UTC (rev 10156)
@@ -132,7 +132,7 @@
FcPattern *fc_pattern;
FcBool scalable;
- fc_pattern = FcNameParse(list);
+ fc_pattern = FcNameParse((unsigned char *)list);
// load the system config
FcConfigSubstitute(0, fc_pattern, FcMatchPattern);
Modified: trunk/planarity/version.h
===================================================================
--- trunk/planarity/version.h 2005-10-13 18:05:13 UTC (rev 10155)
+++ trunk/planarity/version.h 2005-10-14 12:22:47 UTC (rev 10156)
@@ -1,2 +1,2 @@
#define VERSION "$Id$ "
-/* DO NOT EDIT: Automated versioning hack [Wed Oct 5 08:22:03 EDT 2005] */
+/* DO NOT EDIT: Automated versioning hack [Fri Oct 14 08:19:48 EDT 2005] */
More information about the commits
mailing list