/* calculates the control points for a spline segment */ void get_control_points_backward(NODE n1, NODE n2, int points[8]) { fixed dist = fixmul(node_dist(n1, n2), curviness); points[0] = n1.x; points[1] = n1.y; points[2] = n1.x - fixtoi(fixmul(fixcos(n1.tangent), dist)); points[3] = n1.y - fixtoi(fixmul(fixsin(n1.tangent), dist)); points[4] = n2.x + fixtoi(fixmul(fixcos(n2.tangent), dist)); points[5] = n2.y + fixtoi(fixmul(fixsin(n2.tangent), dist)); points[6] = n2.x; points[7] = n2.y; }
/* moves a sprite along the spline path */ void walk(void) { #define MAX_POINTS 256 int points[8]; int x[MAX_POINTS], y[MAX_POINTS]; int n, i; int npoints; int ox, oy; acquire_screen(); clear_to_color(screen, makecol(255, 255, 255)); for (i=1; i<node_count-1; i++) draw_node(i); release_screen(); do { poll_mouse(); } while (mouse_b); clear_keybuf(); ox = -16; oy = -16; xor_mode(TRUE); for (n=1; n < node_count-2; n++) { npoints = (fixtoi(node_dist(nodes[n], nodes[n+1]))+3) / 4; if (npoints < 1) npoints = 1; else if (npoints > MAX_POINTS) npoints = MAX_POINTS; get_control_points(nodes[n], nodes[n+1], points); calc_spline(points, npoints, x, y); for (i=1; i<npoints; i++) { vsync(); acquire_screen(); circlefill(screen, ox, oy, 6, palette_color[2]); circlefill(screen, x[i], y[i], 6, palette_color[2]); release_screen(); ox = x[i]; oy = y[i]; poll_mouse(); if ((keypressed()) || (mouse_b)) goto getout; } } getout: xor_mode(FALSE); do { poll_mouse(); } while (mouse_b); clear_keybuf(); }
/* * Single source shortest path algorithm (Dijkstra's algorithm). */ static int shortest_path(double *nodeArray, int num_nodes, double *edgeArray, int num_edges, int start_index, double dimdist[3], double radius, double *lastNodeList, int geoflag) { int i, cnt, num_nbhrs, curNodeIdx, curNhbrIdx, firstNodeOffset; double *node, *new_node, *nbhrs, *nbhrdists, new_dist; PQueue *PQ; /* Initialize distance to HUGE_VAL. */ for (i=0, node=&nodeArray[DIST]; i<num_nodes; i++, node+=NUM_ATTRS) *node = HUGE_VAL; /* Allocate priority queue and insert start_index as first node. */ PQ = make_pqueue(num_nodes); node = NODEN(nodeArray,start_index-1); node[DIST] = 0.0; if (lastNodeList != NULL) { lastNodeList[start_index-1] = 0; } pqueue_insert(PQ, (PQueueNode)node); firstNodeOffset = ((int)NODEN(nodeArray,0)); /* Dijkstra's algorithm. */ cnt = 0; while (!pqueue_empty_p(PQ)) { node = (double *) pqueue_extract_min(PQ); curNodeIdx = (int)(((int)(node) - firstNodeOffset) / (8*NUM_ATTRS)) + 1; node[DIST] = -node[DIST]; /* computed */ cnt++; /* Relax all the neighboring nodes. */ num_nbhrs = (int) node[NUM_NBHRS]; /* Get the geodesic distances to the neighbors. */ if (geoflag == 1) { nbhrs = EDGEN(edgeArray,(((int)node[NBHRS])-1)); nbhrdists = EDGEN(edgeArray,(((int)node[NBHRS])-1)) + 1; } else { nbhrs = &edgeArray[((int)node[NBHRS])-1]; } for (i=0; i<num_nbhrs; i++) { if (geoflag == 1) { curNhbrIdx = ((int)nbhrs[2*i]); new_node = NODEN(nodeArray,((int)nbhrs[2*i])-1); } else { curNhbrIdx = (((int)nbhrs[i])); new_node = NODEN(nodeArray,((int)nbhrs[i])-1); } if (new_node[DIST]>=0) { /* not computed yet */ /* node[DIST] has been negated a couple of lines above. * so, we need to negate it again to get the actual * (positive) distance. * -node[DIST] is the distance from our working node * to the start point. node_dist() is the distance * between our working node and its ith neighbor. */ /* 08.05.98 SJC * If geoflag == 1, use the geodesic edge distance. */ if (geoflag == 1) { new_dist = -node[DIST] + nbhrdists[2*i]; } else { new_dist = -node[DIST] + node_dist(node, new_node, dimdist); } if (new_dist<radius) { /* If this is the first time that we've gotten here, we * use this new distance and add the node into the * priority queue. */ if (new_node[DIST]==HUGE_VAL) { new_node[DIST] = new_dist; if (lastNodeList != NULL) { lastNodeList[curNhbrIdx - 1] = curNodeIdx; } pqueue_insert(PQ, (PQueueNode)new_node); } /* Otherwise, if the new distance is less than * the previously computed distance, then we pick * the new (shorter) distance and adjust its * position in the priority queue. */ else { if (new_dist<new_node[DIST]) { new_node[DIST] = new_dist; if (lastNodeList != NULL) { lastNodeList[curNhbrIdx - 1] = curNodeIdx; } pqueue_deckey(PQ, (PQueueNode)new_node); } } } } } } free_pqueue(PQ); return(cnt); }