예제 #1
0
/*!
   \brief Find shortest path.

   Costs for 'from' and 'to' nodes are not considered (SP found even if
   'from' or 'to' are 'closed' (costs = -1) and costs of these
   nodes are not added to SP costs result.

   \param graph pointer to graph structure
   \param from from node
   \param to to node
   \param List list of line ids
   \param cost costs value

   \return number of segments
   \return 0 is correct for from = to, or List == NULL ), ? sum of costs is better return value,
   \return -1 destination unreachable
 */
int
Vect_graph_shortest_path(dglGraph_s * graph, int from, int to, struct ilist *List,
			 double *cost)
{
    int i, line, *pclip, cArc, nRet;
    dglSPReport_s *pSPReport;
    dglInt32_t nDistance;

    G_debug(3, "Vect_graph_shortest_path(): from = %d, to = %d", from, to);

    /* Note : if from == to dgl goes to nearest node and returns back (dgl feature) => 
     *         check here for from == to */

    if (List != NULL)
	Vect_reset_list(List);

    /* Check if from and to are identical, otherwise dglib returns path to neares node and back! */
    if (from == to) {
	if (cost != NULL)
	    *cost = 0;
	return 0;
    }

    From_node = from;

    pclip = NULL;
    if (List != NULL) {
	nRet =
	    dglShortestPath(graph, &pSPReport, (dglInt32_t) from,
			    (dglInt32_t) to, clipper, pclip, NULL);
    }
    else {
	nRet =
	    dglShortestDistance(graph, &nDistance, (dglInt32_t) from,
				(dglInt32_t) to, clipper, pclip, NULL);
    }

    if (nRet == 0) {
	if (cost != NULL)
	    *cost = PORT_DOUBLE_MAX;
	return -1;
    }
    else if (nRet < 0) {
	G_warning(_("dglShortestPath error: %s"), dglStrerror(graph));
	return -1;
    }

    if (List != NULL) {
	for (i = 0; i < pSPReport->cArc; i++) {
	    line = dglEdgeGet_Id(graph, pSPReport->pArc[i].pnEdge);
	    G_debug(2, "From %ld to %ld - cost %ld user %d distance %ld",
		    pSPReport->pArc[i].nFrom, pSPReport->pArc[i].nTo,
		    /* this is the cost from clip() */
		    dglEdgeGet_Cost(graph, pSPReport->pArc[i].pnEdge) / 1000,
		    line, pSPReport->pArc[i].nDistance);
	    Vect_list_append(List, line);
	}
    }

    if (cost != NULL) {
	if (List != NULL)
	    *cost = (double)pSPReport->nDistance / 1000;
	else
	    *cost = (double)nDistance / 1000;
    }

    if (List != NULL) {
	cArc = pSPReport->cArc;
	dglFreeSPReport(graph, pSPReport);
    }
    else
	cArc = 0;

    return (cArc);
}
예제 #2
0
int main(int argc, char **argv)
{
    dglGraph_s graph;
    dglInt32_t from, to;

    int fd, nret, version;
    dglSPReport_s *pReport;
    dglInt32_t nDistance;
    dglSPCache_s spCache;
    ClipperContext_s clipctx, *pclipctx;

    /* program options
     */
    char *pszFilein;
    char *pszFrom;
    char *pszTo;
    char *pszDiscard;
    char *pszVersion;
    Boolean fDistance;
    Boolean fUnflatten;

    GNO_BEGIN			/*short       long        default     variable        help */
	GNO_OPTION("g", "graph", NULL, &pszFilein, "graph file to view")
	GNO_OPTION("v", "version", NULL, &pszVersion, "alter graph version")
	GNO_OPTION("f", "from", NULL, &pszFrom, "from-node id")
	GNO_OPTION("t", "to", NULL, &pszTo, "to-node id")
	GNO_OPTION("d", "discard", NULL, &pszDiscard,
		   "node to discard in clipper")
	GNO_SWITCH("D", "distance", False, &fDistance,
		   "Report shortest distance only")
	GNO_SWITCH("U", "unflatten", False, &fUnflatten,
		   "Unflatten the graph before processing")
    GNO_END if (GNO_PARSE(argc, argv) < 0)
    {
	return 1;
    }
    /* options parsed
     */

    if (pszFilein == NULL || pszFrom == NULL || pszTo == NULL) {
	GNO_HELP("incomplete parameters");
	return 1;
    }

    if (pszDiscard) {
	clipctx.node_to_discard = atol(pszDiscard);
	pclipctx = &clipctx;
    }
    else
	pclipctx = NULL;

    if (pszVersion) {
	version = atoi(pszVersion);
    }

    fd = open(pszFilein, O_RDONLY);
    if (fd < 0) {
	perror("open");
	return 1;
    }

    nret = dglRead(&graph, fd);

    close(fd);

    if (nret < 0) {
	fprintf(stderr, "dglRead error: %s\n", dglStrerror(&graph));
	return 1;
    }

    if (fUnflatten)
	dglUnflatten(&graph);

    if (pszVersion)
	dglSet_Version(&graph, version);

    from = atol(pszFrom);
    to = atol(pszTo);

    printf("shortest path: from-node %ld - to-node %ld\n\n", from, to);

    dglInitializeSPCache(&graph, &spCache);

    if (fDistance == False) {
	nret =
	    dglShortestPath(&graph, &pReport, from, to, clipper, pclipctx,
			    &spCache);

	if (nret == 0) {
	    printf("destination node is unreachable\n\n");
	}
	else if (nret < 0) {
	    fprintf(stderr, "dglShortestPath error: %s\n",
		    dglStrerror(&graph));
	}
	else {
	    int i;

	    printf
		("shortest path report: total edges %ld - total distance %ld\n",
		 pReport->cArc, pReport->nDistance);

	    for (i = 0; i < pReport->cArc; i++) {
		printf("edge[%d]: from %ld to %ld - travel cost %ld - user edgeid %ld - distance from start node %ld\n", i, pReport->pArc[i].nFrom, pReport->pArc[i].nTo, dglEdgeGet_Cost(&graph, pReport->pArc[i].pnEdge),	/* this is the cost from clip() */
		       dglEdgeGet_Id(&graph, pReport->pArc[i].pnEdge),
		       pReport->pArc[i].nDistance);
	    }
	    dglFreeSPReport(&graph, pReport);
	}
    }
    else {
	nret =
	    dglShortestDistance(&graph, &nDistance, from, to, clipper,
				pclipctx, &spCache);

	if (nret == 0) {
	    if (dglErrno(&graph) == 0) {
		printf("destination node is unreachable\n\n");
	    }
	}
	else if (nret < 0) {
	    fprintf(stderr, "dglShortestDistance error: %s\n",
		    dglStrerror(&graph));
	}
	else {
	    printf("shortest distance: %ld\n", nDistance);
	}
    }

    dglReleaseSPCache(&graph, &spCache);
    dglRelease(&graph);

    return 0;

}