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); }