Example #1
0
int main(int argc, char **argv)
{
    dglGraph_s graph;
    int fd;
    int nret;

    /* program options
     */
    char *pszFilein;

    GNO_BEGIN			/* short  long        default     variable        help */
	GNO_OPTION("g", "graph", NULL, &pszFilein, "Graph file to view")
	GNO_END if (GNO_PARSE(argc, argv) < 0) {
	return 1;
    }
    /*
     * options parsed
     */

    if (pszFilein == NULL) {
	GNO_HELP("Incomplete parameters");
	return 1;
    }

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

    nret = dglRead(&graph, fd);

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

    close(fd);

    /* print the header
     */
    fprintf(stdout, "Version: %d\n", graph.Version);
    fprintf(stdout, "Byte Order: %s\n",
	    (graph.Endian ==
	     DGL_ENDIAN_LITTLE) ? "Little Endian" : "Big Endian");
    fprintf(stdout, "Node Attribute Size:  %ld\n", graph.NodeAttrSize);
    fprintf(stdout, "Edge Attribute Size:  %ld\n", graph.EdgeAttrSize);
    fprintf(stdout,
	    "Counters:  %ld Edges - %ld Nodes: %ld HEAD / %ld TAIL / %ld ALONE\n",
	    graph.cEdge, graph.cNode, graph.cHead, graph.cTail, graph.cAlone);
    fprintf(stdout, "Opaque Settings:\n");
    fprintf(stdout, "%10ld %10ld %10ld %10ld\n",
	    graph.aOpaqueSet[0], graph.aOpaqueSet[1],
	    graph.aOpaqueSet[2], graph.aOpaqueSet[3]);
    fprintf(stdout, "%10ld %10ld %10ld %10ld\n",
	    graph.aOpaqueSet[4], graph.aOpaqueSet[5],
	    graph.aOpaqueSet[6], graph.aOpaqueSet[7]);
    fprintf(stdout, "%10ld %10ld %10ld %10ld\n",
	    graph.aOpaqueSet[8], graph.aOpaqueSet[9],
	    graph.aOpaqueSet[10], graph.aOpaqueSet[11]);
    fprintf(stdout, "%10ld %10ld %10ld %10ld\n",
	    graph.aOpaqueSet[12], graph.aOpaqueSet[13],
	    graph.aOpaqueSet[14], graph.aOpaqueSet[15]);
    fprintf(stdout, "Total Cost: %lld\n", graph.nnCost);
    fprintf(stdout, "--\n");


    {
	dglInt32_t *pnode;
	dglNodeTraverser_s traverser;

	dglNode_T_Initialize(&traverser, &graph);
	for (pnode = dglNode_T_First(&traverser); pnode;
	     pnode = dglNode_T_Next(&traverser)) {
	    _print_node(&graph, pnode, stdout);
	}
	dglNode_T_Release(&traverser);
    }

    printf("\n");
    dglRelease(&graph);
    return 0;

}
Example #2
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);
}
Example #3
0
int main(int argc, char **argv)
{
    FILE *fp;
    char sz[1024];
    char szw[1024];
    int nret;
    regmatch_t aregm[64];
    dglInt32_t nVersion;
    dglInt32_t nNodeAttrSize;
    dglInt32_t nEdgeAttrSize;
    dglInt32_t anOpaque[16];
    int i, fd, cOut;

    regex_t reVersion;
    regex_t reByteOrder;
    regex_t reNodeAttrSize;
    regex_t reEdgeAttrSize;
    regex_t reCounters;
    regex_t reOpaque;
    regex_t reNodeFrom;
    regex_t reNodeAttr;
    regex_t reEdge;
    regex_t reToNodeAttr;
    regex_t reEdgeAttr;


    dglInt32_t nNodeFrom, nNodeTo, nUser, nCost;

    int fInOpaque;
    int fInBody;

    unsigned char *pbNodeAttr, *pbEdgeAttr, *pbToNodeAttr;

    STRUCT_STAT statdata;

    dglGraph_s graphOut;

    /* program options
     */
    char *pszFilein;
    char *pszGraphout;

    GNO_BEGIN			/* short  long        default     variable        help */
	GNO_OPTION("i", "input", NULL, &pszFilein, "Input text file")
	GNO_OPTION("o", "output", NULL, &pszGraphout, "Output graph file")
	GNO_END if (GNO_PARSE(argc, argv) < 0) {
	return 1;
    }
    /*
     * options parsed
     */

    if (pszFilein == NULL) {
	GNO_HELP("... usage");
	return 1;
    }

    /*
     * compile header expressions
     */
    printf("Compile header expressions...");
    fflush(stdout);
    i = 0;
    if (regcomp(&reVersion, "^Version:[ ]+([0-9]+)", REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    if (regcomp(&reByteOrder, "^Byte Order:[ ]+(.+)", REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    if (regcomp
	(&reNodeAttrSize, "^Node Attribute Size:[ ]+([0-9]+)",
	 REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    if (regcomp
	(&reEdgeAttrSize, "^Edge Attribute Size:[ ]+([0-9]+)",
	 REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    if (regcomp(&reCounters, "^Counters:[ ]+.*", REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    if (regcomp(&reOpaque, "^Opaque Settings:", REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    printf("done.\n");

    /*
     * compile body expressions
     */

    printf("Compile body expressions...");
    fflush(stdout);
    if (regcomp(&reNodeFrom, "^HEAD ([0-9]+)[ ]*- [HT/']+", REG_EXTENDED) !=
	0)
	goto regc_error;
    i++;
    if (regcomp(&reNodeAttr, ".*HEAD ATTR [[]([0-9a-fA-F ]+)]", REG_EXTENDED)
	!= 0)
	goto regc_error;
    i++;

    if (regcomp
	(&reEdge,
	 "^EDGE #([0-9]+)[ ]*: TAIL ([0-9]+)[ ]*- [HT/']+[ ]+- COST ([0-9]+)[ ]*- ID ([0-9]+)",
	 REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    if (regcomp
	(&reToNodeAttr, ".*TAIL ATTR [[]([0-9a-fA-F ]+)]", REG_EXTENDED) != 0)
	goto regc_error;
    i++;
    if (regcomp(&reEdgeAttr, ".*EDGE ATTR [[]([0-9a-fA-F ]+)]", REG_EXTENDED)
	!= 0)
	goto regc_error;
    i++;

    printf("done.\n");

    goto regc_ok;




  regc_error:
    fprintf(stderr, "regex compilation error %d\n", i);
    exit(1);





  regc_ok:

    if ((fp = fopen(pszFilein, "r")) == NULL) {
	perror("fopen");
	return 1;
    }

    fstat(fileno(fp), &statdata);

    fInOpaque = 0;
    fInBody = 0;

    nNodeAttrSize = 0;
    nEdgeAttrSize = 0;
    pbNodeAttr = NULL;
    pbToNodeAttr = NULL;
    pbEdgeAttr = NULL;

    cOut = 0;

    while (fgets(sz, sizeof(sz), fp)) {
#ifndef VERBOSE
	if (!(cOut++ % 512) || G_ftell(fp) == statdata.st_size)
	    printf("Parse input file ... status: %ld/%ld\r", G_ftell(fp),
		   statdata.st_size);
	fflush(stdout);
#endif

#ifdef VERYVERBOSE
	printf("<<<%s>>>\n", sz);
#endif
	if (fInOpaque == 0 && fInBody == 0) {
	    if (regexec(&reVersion, sz, 64, aregm, 0) == 0) {
		_regmtostring(szw, sizeof(szw), sz, &aregm[1]);
		nVersion = atoi(szw);
#ifdef VERYVERBOSE
		printf("-- version %d\n", nVersion);
#endif
	    }
	    else if (regexec(&reByteOrder, sz, 64, aregm, 0) == 0) {
	    }
	    else if (regexec(&reNodeAttrSize, sz, 64, aregm, 0) == 0) {
		_regmtostring(szw, sizeof(szw), sz, &aregm[1]);
		nNodeAttrSize = atoi(szw);
		if (nNodeAttrSize) {
		    pbNodeAttr = (unsigned char *)malloc(nNodeAttrSize);
		    if (pbNodeAttr == NULL) {
			fprintf(stderr, "Memory Exhausted\n");
			exit(1);
		    }
		    pbToNodeAttr = (unsigned char *)malloc(nNodeAttrSize);
		    if (pbToNodeAttr == NULL) {
			fprintf(stderr, "Memory Exhausted\n");
			exit(1);
		    }
		}
#ifdef VERYVERBOSE
		printf("-- node attr size %d\n", nNodeAttrSize);
#endif
	    }
	    else if (regexec(&reEdgeAttrSize, sz, 64, aregm, 0) == 0) {
		_regmtostring(szw, sizeof(szw), sz, &aregm[1]);
		nEdgeAttrSize = atoi(szw);
		if (nEdgeAttrSize > 0) {
		    pbEdgeAttr = (unsigned char *)malloc(nEdgeAttrSize);
		    if (pbEdgeAttr == NULL) {
			fprintf(stderr, "Memory Exhausted\n");
			exit(1);
		    }
		}
#ifdef VERYVERBOSE
		printf("-- edge attr size %d\n", nEdgeAttrSize);
#endif
	    }
	    else if (regexec(&reOpaque, sz, 64, aregm, 0) == 0) {
#ifdef VERYVERBOSE
		printf("-- opaque...\n");
#endif
		fInOpaque = 1;
	    }
	    else if (strncmp(sz, "--", 2) == 0) {
		nret = dglInitialize(&graphOut,
				     nVersion,
				     nNodeAttrSize, nEdgeAttrSize, anOpaque);
		if (nret < 0) {
		    fprintf(stderr, "dglInitialize error %s\n",
			    dglStrerror(&graphOut));
		    exit(1);
		}
#ifdef VERBOSE
		printf("Initialize: Version=%ld NodeAttr=%ld EdgeAttr=%ld\n",
		       nVersion, nNodeAttrSize, nEdgeAttrSize);
#endif
		fInBody = 1;
	    }
	}
	else if (fInOpaque > 0 && fInBody == 0) {
	    if (fInOpaque == 1) {
		sscanf(sz, "%ld %ld %ld %ld",
		       &anOpaque[0],
		       &anOpaque[1], &anOpaque[2], &anOpaque[3]);
		fInOpaque++;
#ifdef VERYVERBOSE
		printf("opaque 1: %ld %ld %ld %ld\n",
		       anOpaque[0], anOpaque[1], anOpaque[2], anOpaque[3]);
#endif

	    }
	    else if (fInOpaque == 2) {
		sscanf(sz, "%ld %ld %ld %ld",
		       &anOpaque[4],
		       &anOpaque[5], &anOpaque[6], &anOpaque[7]);
#ifdef VERYVERBOSE
		printf("opaque 2: %ld %ld %ld %ld\n",
		       anOpaque[4], anOpaque[5], anOpaque[6], anOpaque[7]);
#endif
		fInOpaque++;
	    }
	    else if (fInOpaque == 3) {
		sscanf(sz, "%ld %ld %ld %ld",
		       &anOpaque[8],
		       &anOpaque[9], &anOpaque[10], &anOpaque[11]);
#ifdef VERYVERBOSE
		printf("opaque 3: %ld %ld %ld %ld\n",
		       anOpaque[8], anOpaque[9], anOpaque[10], anOpaque[11]);
#endif
		fInOpaque++;
	    }
	    else if (fInOpaque == 4) {
		sscanf(sz, "%ld %ld %ld %ld",
		       &anOpaque[12],
		       &anOpaque[13], &anOpaque[14], &anOpaque[15]);
#ifdef VERYVERBOSE
		printf("opaque 4: %ld %ld %ld %ld\n",
		       anOpaque[12],
		       anOpaque[13], anOpaque[14], anOpaque[15]);
#endif
		fInOpaque = 0;
	    }
	}
	else if (fInBody == 1) {
	    if (regexec(&reNodeFrom, sz, 64, aregm, 0) == 0) {
		_regmtostring(szw, sizeof(szw), sz, &aregm[1]);
#ifdef VERYVERBOSE
		printf("node from snippet = %s\n", szw);
#endif
		nNodeFrom = atol(szw);
		if (nNodeAttrSize > 0) {
		    if (regexec(&reNodeAttr, sz, 64, aregm, 0) == 0) {
			_regmtostring(szw, sizeof(szw), sz, &aregm[1]);
			if (_sztoattr(pbNodeAttr, nNodeAttrSize, szw) !=
			    nNodeAttrSize) {
			    fprintf(stderr, "node attr size mismatch\n");
			}
#ifdef VERYVERBOSE
			{
			    int k;

			    for (k = 0; k < nNodeAttrSize; k++) {
				printf("%02x", pbNodeAttr[k]);
			    }
			    printf("\n");
			}
#endif
		    }
		}
	    }
	    else if (regexec(&reEdge, sz, 64, aregm, 0) == 0) {
		_regmtostring(szw, sizeof(szw), sz, &aregm[2]);
		nNodeTo = atol(szw);
		_regmtostring(szw, sizeof(szw), sz, &aregm[3]);
		nCost = atol(szw);
		_regmtostring(szw, sizeof(szw), sz, &aregm[4]);
		nUser = atol(szw);
		if (nEdgeAttrSize > 0) {
		    if (regexec(&reEdgeAttr, sz, 64, aregm, 0) == 0) {
			_regmtostring(szw, sizeof(szw), sz, &aregm[1]);
			if (_sztoattr(pbEdgeAttr, nEdgeAttrSize, szw) !=
			    nEdgeAttrSize) {
			    fprintf(stderr, "edge attr size mismatch\n");
			}
#ifdef VERYVERBOSE
			{
			    int k;

			    for (k = 0; k < nEdgeAttrSize; k++) {
				printf("%02x", pbEdgeAttr[k]);
			    }
			    printf("\n");
			}
#endif
		    }
		}
		if (nNodeAttrSize > 0) {
		    if (regexec(&reToNodeAttr, sz, 64, aregm, 0) == 0) {
			_regmtostring(szw, sizeof(szw), sz, &aregm[1]);
			if (_sztoattr(pbToNodeAttr, nNodeAttrSize, szw) !=
			    nNodeAttrSize) {
			    fprintf(stderr, "to node attr size mismatch\n");
			}
#ifdef VERYVERBOSE
			{
			    int k;

			    for (k = 0; k < nNodeAttrSize; k++) {
				printf("%02x", pbToNodeAttr[k]);
			    }
			    printf("\n");
			}
#endif
		    }
		}
		nret = dglAddEdgeX(&graphOut,
				   nNodeFrom,
				   nNodeTo,
				   nCost,
				   nUser,
				   pbNodeAttr, pbToNodeAttr, pbEdgeAttr, 0);

		if (nret < 0) {
		    fprintf(stderr, "dglAddEdge error %s\n",
			    dglStrerror(&graphOut));
		    exit(1);
		}
#ifdef VERBOSE
		printf("AddEdge: from=%ld to=%ld cost=%ld user=%ld\n",
		       nNodeFrom, nNodeTo, nCost, nUser);
#endif
	    }
	}
    }
#ifndef VERBOSE
    printf("\ndone.\n");
#endif

    fclose(fp);

    regfree(&reVersion);
    regfree(&reByteOrder);
    regfree(&reNodeAttrSize);
    regfree(&reEdgeAttrSize);
    regfree(&reCounters);
    regfree(&reOpaque);
    regfree(&reNodeFrom);
    regfree(&reNodeAttr);
    regfree(&reEdge);
    regfree(&reToNodeAttr);
    regfree(&reEdgeAttr);

    if (pbNodeAttr)
	free(pbNodeAttr);
    if (pbToNodeAttr)
	free(pbToNodeAttr);
    if (pbEdgeAttr)
	free(pbEdgeAttr);


    printf("Flatten...");
    fflush(stdout);
    nret = dglFlatten(&graphOut);
    if (nret < 0) {
	fprintf(stderr, "dglFlatten error %s\n", dglStrerror(&graphOut));
	exit(1);
    }
    printf("done.\n");

    if (pszGraphout) {
	fd = open(pszGraphout, O_WRONLY | O_CREAT | O_TRUNC, 0666);
	if (fd < 0) {
	    perror("open");
	    exit(1);
	}

	printf("Write <%s>...", pszGraphout);
	fflush(stdout);
	nret = dglWrite(&graphOut, fd);
	if (nret < 0) {
	    fprintf(stderr, "dglWrite error %s\n", dglStrerror(&graphOut));
	    exit(1);
	}
	printf("done.\n");
	close(fd);
    }

    printf("Release...");
    fflush(stdout);
    dglRelease(&graphOut);
    printf("done.\n");

    return 0;
}
Example #4
0
int main(int argc, char **argv)
{
    dglGraph_s graph;

#define MY_MAX_COMPONENTS	1024
    dglGraph_s agraphComponents[MY_MAX_COMPONENTS];
    int nret, fd, i, cComponents;
    char szGraphOutFilename[1024];

    /* program options
     */
    char *pszGraph;
    char *pszGraphOut;

    GNO_BEGIN			/* short   long                default     variable        help */
	GNO_OPTION("g", "graph", NULL, &pszGraph, "Input Graph file")
	GNO_OPTION("o", "graphout", NULL, &pszGraphOut, "Output Graph file")
	GNO_END if (GNO_PARSE(argc, argv) < 0) {
	return 1;
    }
    /*
     * options parsed
     */

    if (pszGraph == NULL || pszGraphOut == NULL) {
	GNO_HELP("components usage");
	return 1;
    }


    printf("Graph read:\n");
    if ((fd = open(pszGraph, O_RDONLY)) < 0) {
	perror("open");
	return 1;
    }
    nret = dglRead(&graph, fd);
    if (nret < 0) {
	fprintf(stderr, "dglRead error: %s\n", dglStrerror(&graph));
	return 1;
    }
    close(fd);
    printf("Done.\n");



    printf("Graph depth components spanning:\n");
    cComponents =
	dglDepthComponents(&graph, agraphComponents, MY_MAX_COMPONENTS,
			   _clipper, NULL);
    if (cComponents < 0) {
	fprintf(stderr, "dglDepthSpanning error: %s\n", dglStrerror(&graph));
	return 1;
    }
    printf("Done.\n");

    printf("Connected Component(s) Found: %d\n", cComponents);

    for (i = 0; i < cComponents; i++) {
	printf("Component %d of %d: ", i + 1, cComponents);
	fflush(stdout);

	printf("[flatten...");
	fflush(stdout);
	nret = dglFlatten(&agraphComponents[i]);
	printf("done] ");
	fflush(stdout);

	if (dglGet_EdgeCount(&agraphComponents[i]) > 0) {
	    if (pszGraphOut) {
		snprintf(szGraphOutFilename, sizeof(szGraphOutFilename),
			 "%s-component-%d", pszGraphOut, i);
		printf("[write <%s>...", szGraphOutFilename);
		fflush(stdout);
		if ((fd =
		     open(szGraphOutFilename, O_WRONLY | O_CREAT | O_TRUNC,
			  0666)) < 0) {
		    perror("open");
		    return 1;
		}
		dglWrite(&agraphComponents[i], fd);
		if (nret < 0) {
		    fprintf(stderr, "dglWrite error: %s\n",
			    dglStrerror(&graph));
		    return 1;
		}
		close(fd);
		printf("done] ");
		fflush(stdout);
	    }
	}
	else {
	    printf("component is empty. No output produced.\n");
	}

	printf("[release...");
	dglRelease(&agraphComponents[i]);
	printf("done]\n");
    }

    dglRelease(&graph);
    return 0;
}
Example #5
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;

}