void	TIGERImport(
			const	ChainInfoMap&		chains,
			const	LandmarkInfoMap&	landmarks,
			const	PolygonInfoMap&		polygons,
			Pmwx&						outMap)
{
	// Our planar map MUST be empty!

	// First we go in and insert every segment from the TIGER database into our map.
	// We keep a table from coordinates into the map so we can avoid doing a search
	// when we have a segment that is already at least partially inserted.

	VertexIndex		vertices;
	EdgeIndex		edges;
	FaceIndex		faces;

	set<TLID>		badTLIDs;

	int	gSegs = 0, gBad = 0, gDupes = 0;
	set<TLID>	tlids;
#if DO_CHECKS
	map<string, TLID>	lines;
#endif

	for (ChainInfoMap::const_iterator chain = chains.begin(); chain != chains.end(); ++chain)
	{
		int i = LookupNetCFCC(chain->second.cfcc.c_str());

		vector<RawCoordPair>	pts = chain->second.shape;
		pts.insert(pts.begin(), chain->second.start);
		pts.insert(pts.end(), chain->second.end);

		if (tlids.find(chain->first) != tlids.end())
		{
//			printf("WARNING: about to dupe a TLID!\n");
			continue;
		}
		tlids.insert(chain->first);

		for (int n = 1; n < pts.size(); ++n)
		{
			++gSegs;

#if DO_CHECKS
			string	masterkey, k1 = RawCoordToKey(pts[n-1]), k2 = RawCoordToKey(pts[n]);
			if (k1 < k2)
				masterkey = k1 + k2;
			else
				masterkey = k2 + k1;

			map<string, TLID>::iterator tlidCheck = lines.find(masterkey);
			if (tlidCheck != lines.end())
			{
				printf("WARNING: already did this seg (by key), old TLID = %ul, new TLID = %ul!\n", tlidCheck->second, chain->first);
				printf("Sequence in question is: %s\n", tlidCheck->first.c_str());
				continue;
			}
			lines.insert(map<string, TLID>::value_type(masterkey, chain->first));
#endif

			try {

				Pmwx::Halfedge_handle he = InsertOneSegment(pts[n-1], pts[n], vertices, outMap);
				if (he != outMap.halfedges_end())
				{
					// InsertOneSegment always returns the dominant half-edge.  Tag it with
					// our road type, underpassing info, and our TLID.
					if (i != -1)
					{
						GISNetworkSegment_t nl;
						nl.type = kRoadCodes[i].network_type;
						he->mSegments.push_back(nl);
						he->mParams[gis_TIGER_IsUnderpassing] = kRoadCodes[i].underpassing;
					}
					he->mParams[gis_TIGER_TLID] = chain->first;
					he->twin()->mParams[gis_TIGER_TLID] = chain->first;
					edges[chain->first] = he;
				} else {
					printf("Got dupe seg, CFCC = %s, name = %s, tlid = %d\n", chain->second.cfcc.c_str(), chain->second.name.c_str(), chain->first);
					++gDupes;
				}

			} catch (...) {
				++gBad;
				printf("Got bad seg, CFCC = %s, name = %s, tlid = %d\n", chain->second.cfcc.c_str(), chain->second.name.c_str(), chain->first);
				badTLIDs.insert(chain->first);
			}

			if ((gSegs % 10000) == 0)
			{
				fprintf(stdout, ".");
				fflush(stdout);
			}
		}
	}
	std::cout << "\nTotal " << gSegs << " bad " << gBad << " dupes " << gDupes << "\n";

	double	elapsed;
	unsigned long	calls;
	double	ave;

	zeroV.GetStats(elapsed, calls);
	ave = elapsed / (double) calls;
	printf("In-face insertion: %f total, %d calls, %f average.\n", elapsed, calls, ave);

	oneV.GetStats(elapsed, calls);
	ave = elapsed / (double) calls;
	printf("One-V Insertion: %f total, %d calls, %f average.\n", elapsed, calls, ave);

	twoV.GetStats(elapsed, calls);
	ave = elapsed / (double) calls;
	printf("Two-V insertion: %f total, %d calls, %f average.\n", elapsed, calls, ave);


	// Now we go in and apply our polygon data.  We have set the dominant flag to be the halfedge
	// that goes in the same direction as the tiger database.  Since CGAL faces have CCW outer
	// boundaries, that means that the left hand poly of a TLID is adjacent to the dominant
	// halfedge.



	int	gPolys = 0, gMissingTLIDs = 0, gBadEdges = 0, gBadBackLink = 0, gDeadTLID = 0;

	for (PolygonInfoMap::const_iterator poly = polygons.begin(); poly != polygons.end(); ++poly)
	{
		if (poly->first == WORLD_POLY)
			continue;
		++gPolys;
		set<TLID>		ourTLIDs;
		for (DirectedTLIDVector::const_iterator t = poly->second.border.begin(); t != poly->second.border.end(); ++t)
			ourTLIDs.insert(t->first);
		vector<TLID>	ourBads;
		set_intersection(ourTLIDs.begin(), ourTLIDs.end(), badTLIDs.begin(), badTLIDs.end(),
						back_insert_iterator<vector<TLID> >(ourBads));
		if (!ourBads.empty())
		{
			printf("Skipped Polygon because one of its TLIDs is missing from the DB!\n");
			++gDeadTLID;
			continue;
		}

		EdgeIndex::iterator edgeIter = edges.find(*ourTLIDs.begin());
		ChainInfoMap::const_iterator tlidIter = chains.find(*ourTLIDs.begin());

		if (edgeIter != edges.end() && tlidIter != chains.end())
		{
			Pmwx::Face_handle		our_face = outMap.faces_end();
			Pmwx::Halfedge_handle	he = edgeIter->second;
			if (!he->mDominant) he = he->twin();
			if (!he->mDominant)
			{
				++gBadEdges;
				printf("WARNING: Halfedge with no dominance!!\n");
				continue;
			}

			if (poly->first == tlidIter->second.lpoly)
			{
				our_face = he->face();
			} else if (poly->first == tlidIter->second.rpoly)
			{
				our_face = he->twin()->face();
			} else  {
				printf("WARNING: TLID from poly not backlinked to our poly!\n");
				++gBadBackLink;
			}

			if (our_face != outMap.faces_end())
			{
				if (poly->second.water)
				{
					our_face->mLandClass = lc_GenericWater;
				}
				faces[poly->first] = our_face;
			}
		} else
			++gMissingTLIDs;
	}


	printf("Polygons: %d, missing TLIDs from indices: %d, edges with no dominance: %d, bad back links: %d, dead TLIDS: %d\n",
			gPolys, gMissingTLIDs, gBadEdges, gBadBackLink, gDeadTLID);





	int	gLand = 0, gNoID = 0, gNoLocAtAll = 0, gPtOnEdge = 0;
	for (LandmarkInfoMap::const_iterator landmark = landmarks.begin();
		landmark != landmarks.end(); ++landmark)
	{
		++gLand;
		int cfcc = LookupAreaCFCC(landmark->second.cfcc.c_str());
		if (cfcc != -1)
		{
			if (!landmark->second.cenid_polyid.empty())
			{
				FaceIndex::iterator theFace = faces.find(landmark->second.cenid_polyid);
				if (theFace != faces.end())
				{
					theFace->second->mLandClass = kAreaCodes[cfcc].land_class;
				} else {
					fprintf(stderr, "WARNING: Cenid/polyid not found.\n");
					++gNoID;
				}

			} else if (!landmark->second.location.first.empty()) {

				if (kAreaCodes[cfcc].allow_from_point)
				{
					try {
						Pmwx::Locate_type	lt;

						Pmwx::Halfedge_handle h =
							outMap.locate(RawCoordToCoord(landmark->second.location), lt);

						if (lt == Pmwx::EDGE || lt == Pmwx::FACE)
						{
							h->face()->mLandClass = kAreaCodes[cfcc].land_class;
						} else {
							++gPtOnEdge;
							fprintf(stderr, "WARNING: Pt land mark on vertex or out of map.\n");
						}
					} catch (...) {
						++gPtOnEdge;
					}
				} else {
					// TODO: Add pt object
				}
			} else {
				fprintf(stderr, "Warning: landmark without polygon or pt.\n");
				gNoLocAtAll++;
			}
		}
	}
	printf("Total landmarks = %d, total with unknown CENID/POLYID = %d, no Loc = %d, pt on edge = %d\n", gLand, gNoID, gNoLocAtAll, gPtOnEdge);
}