double solve() { int i,j,k,l,m; double x1,y1,x2,y2; /* calculate distances and tangent points for each circle pair */ for(i=0;i<2;i++) for(j=0;j<2;j++) for(k=0;k<n;k++) for(l=0;l<n;l++) dist[i][j][k][l]=-1; memset(theta1,0,sizeof(theta1)); memset(theta2,0,sizeof(theta2)); for(i=0;i<2;i++) for(j=0;j<2;j++) for(k=0;k<n;k++) for(l=0;l<n;l++) if(k!=l) { if(k==1) continue; if((k<2 && i) || (l<2 && j)) continue; twocircletangent(circlex[k],circley[k],circler[k], circlex[l],circley[l],circler[l],i,j,&x1,&y1,&x2,&y2); /* for each other circle: check if it collides */ for(m=0;m<n;m++) if(m!=k && m!=l && linecircleintersect(x1,y1,x2,y2, circlex[m],circley[m],circler[m])) goto fail; // printf("ix (%d %d) %d %d\n",i,j,k,l);printf("from circle (%.1f %.1f %d) to (%.1f %.1f %d): (%f %f) (%f %f)\n",circlex[k],circley[k],circler[k],circlex[l],circley[l],circler[l],x1,y1,x2,y2);printf("dist %.10f\n",dist2d(x1,y1,x2,y2)); dist[i][j][k][l]=dist2d(x1,y1,x2,y2); tx1[i][j][k][l]=x1; ty1[i][j][k][l]=y1; tx2[i][j][k][l]=x2; ty2[i][j][k][l]=y2; theta1[i][j][k][l]=getangle(x1,y1,circlex[k],circley[k]); theta2[i][j][k][l]=getangle(x2,y2,circlex[l],circley[l]); fail:; } // for(i=0;i<2;i++) for(j=0;j<2;j++) for(k=0;k<n;k++) for(l=0;l<n;l++) if(dist[i][j][k][l]>-.5) {printf("%d %d %d %d: %f (%.3f %.3f) (%.3f %.3f) (%.2f %.2f)\n",i,j,k,l,dist[i][j][k][l],tx1[i][j][k][l],ty1[i][j][k][l],tx2[i][j][k][l],ty2[i][j][k][l],theta1[i][j][k][l],theta2[i][j][k][l]);} return dijkstra(); }
/*----------------------------------------------------------------------------*/ static void worldmapRedraw() { WorldCoord x; WorldCoord y; float ang; float dist; GlSurface_clear(map_surf, map_color[0]); for (y = 0; y < rct_src.h; y++) { for (x = 0; x < rct_src.w; x++) { GlSurface_drawPixel(map_surf, rct_dest.x + x, rct_dest.y + y, getCol(map_plot[(rct_src.y + y) * map_w + (rct_src.x + x)])); } } /*TODO: maybe store ang and dist*/ ang = angle2d((float)(camlookx - camposx), (float)(camlooky - camposy)); dist = dist2d((float)camlookx, (float)camlooky, (float)camposx, (float)camposy); GlSurface_drawLineCut(map_surf, camposx - rct_src.x + rct_dest.x, camposy - rct_src.y + rct_dest.y, camposx + cos(ang + M_PI_4) * dist - rct_src.x + rct_dest.x, camposy + sin(ang + M_PI_4) * dist - rct_src.y + rct_dest.y, map_color[6]); GlSurface_drawLineCut(map_surf, camposx - rct_src.x + rct_dest.x, camposy - rct_src.y + rct_dest.y, camposx + cos(ang - M_PI_4) * dist - rct_src.x + rct_dest.x, camposy + sin(ang - M_PI_4) * dist - rct_src.y + rct_dest.y, map_color[6]); GuiWidget_redraw(_widget); }
void twocircletangentsub(double x1,double y1,int r1,double x2,double y2,int r2,double *tx1,double *ty1,double *tx2,double *ty2) { double a,b,d=dist2d(x1,y1,x2,y2),x=x2-x1,y=y2-y1,R,X,Y; int r=r2-r1; X=x/d; Y=y/d; R=r/d; /* calculate a,b,c so that line is ax+by+c=0 */ a=R*X-Y*sqrt(1-R*R); b=R*Y+X*sqrt(1-R*R); /* follow the line's normal from the circle centres */ // printf("(r %d %d) line is %f %f\n",r1,r2,a,b); *tx1=x1-a*r1; *ty1=y1-b*r1; *tx2=x2-a*r2; *ty2=y2-b*r2; }