void writeSQL(Site_2 site, PointList polygon, char* outdir) { std::cout << "INSERT INTO " << outdir << " (geom, id) VALUES ("; std::cout << "'POLYGON (("; for (int i = 0; i < polygon.size(); i++) { Point_2 p = polygon.at(i); std::cout << p.x() << " " << p.y(); if (i < polygon.size() - 1) { std::cout << ", "; } } std::cout << "))', " << site.id() << ");" << std::endl; }
void CSVPointListExporter::exportFromDataBase() { if(!QFile::exists(sourseDataBaseFile_)) { qWarning() << sourseDataBaseFile_ << "not exists"; return; } SqlPointListReader reader(sourseDataBaseFile_, sourseTableName_); if(!reader.open()) { qWarning() << sourseDataBaseFile_ << "not open"; return; } QFile targetFile(targetFileName_); if(!targetFile.open(QFile::WriteOnly | QIODevice::Text)) { qWarning() << targetFileName_ << "can't open for writing"; } QTextStream targetFileStream(&targetFile); const IDList idList = reader.readAllItems(); for(int i = 0; i < idList.count(); i++) { const ID& id = idList.at(i); const PointList pointList = reader.read(id); for(int j = 0; j < pointList.count(); j++) { const Point& point = pointList.at(j); targetFileStream << pointList.id() << ";" << point; const bool isLast = ((i + 1) == idList.count()) && ((j + 1) == pointList.count()); if(!isLast) { targetFileStream << '\n'; } } } targetFile.flush(); targetFile.close(); }
void writeGeoJSON(Site_2 site, PointList polygon, char* outdir) { // open an output file for storing the WKT std::stringstream s; s << outdir << "/" << site.id() << ".geojson"; std::string polygonFileName = s.str(); std::cerr << "filename: " << polygonFileName << std::endl; std::ofstream file; file.open(polygonFileName.c_str()); // write data file << "{\"type\":\"Polygon\",\"coordinates\":[["; for (int i = 0; i < polygon.size(); i++) { Point_2 p = polygon.at(i); file << "[" << p.x() << ", " << p.y() << "]"; if (i < polygon.size() - 1) { file << ", "; } } file << "]]}"; file.close(); }
void writeWKT(Site_2 site, PointList polygon, char* outdir) { // open an output file for storing the WKT std::stringstream s; s << outdir << "/" << site.id() << ".wkt"; std::string polygonFileName = s.str(); std::cerr << "filename: " << polygonFileName << std::endl; std::ofstream file; file.open(polygonFileName.c_str()); // write WKT file file << "POLYGON (("; for (int i = 0; i < polygon.size(); i++) { Point_2 p = polygon.at(i); file << p.x() << " " << p.y(); if (i < polygon.size() - 1) { file << ", "; } } file << "))"; file.close(); }
int main(int argc , char* argv[]) { if (argc < 7) { std::cerr << "usage: test <input file> <output folder> " "<format (wkt | geojson | sql)> <weight city> <weight town> <weight village>" << std::endl; exit(1); } char* input = argv[1]; char* outdir = argv[2]; char* format = argv[3]; char* swc = argv[4]; char* swt = argv[5]; char* swv = argv[6]; std::ifstream ifs(input); assert( ifs ); double wc, wt, wv; std::istringstream stmc, stmt, stmv; stmc.str(swc); stmc >> wc; stmt.str(swt); stmt >> wt; stmv.str(swv); stmv >> wv; std::cerr << "using weights: city: " << wc << ", town: " << wt << ", village: " << wv << std::endl; /* * prepare data */ // we use a ScalingFactor(SF) here to stretch input values at the // beginning, and divide by SF in the end. This is used because the // point-generation of the hyperbola class is using some arbitrary // internal decision thresholds to decide how many points to generate for // a certain part of the curve. Rule of thumb is: the higher SF the more // detail is used in approximation of the hyperbolas. double SF = 4000; // read in sites from input file SiteList sites = readSites(ifs, SF, wc, wt, wv); printSites(sites); // calculate bounding box of all input sites (and extend it a little). // Extension is important, because we later add artificial sites which are // actually mirrored on the bounds of this rectangle. If we did not extend // some points would lie on the boundary of the bounding box and so would // their artificial clones. This would complicate the whole stuff a lot :) Iso_rectangle_2 crect = extend(boundingBox(sites), 0.1*SF); std::cerr << "rect: " << crect << std::endl; // a number of artificial sites SiteList artificialSites = createArtificialSites(sites, crect); /* * create Apollonius graph */ Apollonius_graph ag; SiteList::iterator itr; // add all original sites to the apollonius graph for (itr = sites.begin(); itr != sites.end(); ++itr) { Site_2 site = *itr; ag.insert(site); } // add all artificial sites to the apollonius graph for (itr = artificialSites.begin(); itr != artificialSites.end(); ++itr) { Site_2 site = *itr; ag.insert(site); } // validate the Apollonius graph assert( ag.is_valid(true, 1) ); std::cerr << std::endl; /* * create polygons from cells */ // we want an identifier for each vertex within the iteration. // this is a loop iteration counter int vertexIndex = 0; // for each vertex in the apollonius graph (this are the sites) for (All_vertices_iterator viter = ag.all_vertices_begin (); viter != ag.all_vertices_end(); ++viter) { // get the corresponding site Site_2 site = viter->site(); Point_2 point = site.point(); // ignore artifical sites, detect them by their position if (!CGAL::do_intersect(crect, point)) { continue; } std::cerr << "vertex " << ++vertexIndex << std::endl; // we than circulate all incident edges. By obtaining the respective // dual of each edge, we get access to the objects forming the boundary // of each voronoi cell in a proper order. Edge_circulator ecirc = ag.incident_edges(viter), done(ecirc); // this is where we store the polylines std::vector<PointList> polylines; // for each incident edge do { // the program may fail in certain situations without this test. // acutally !is_infinite(edge) is a precondition in ag.dual(edge). if (ag.is_infinite(*ecirc)) { continue; } // NOTE: for this to work, we had to make public the dual function in ApolloniusGraph // change line 542 in "Apollonius_graph_2.h" from "private:" to "public:" Object_2 o = ag.dual(*ecirc); handleDual(o, crect, polylines); } while(++ecirc != done); PointList polygon = buildPolygon(site, polylines); for (int i = 0; i < polygon.size(); i++) { Point_2& p = polygon.at(i); p = Point_2(p.x()/SF, p.y()/SF); } if(std::string(format) == "geojson") { writeGeoJSON(site, polygon, outdir); } else if(std::string(format) == "sql") { writeSQL(site, polygon, outdir); } else { writeWKT(site, polygon, outdir); } // check each point for (int i = 0; i < polygon.size(); i++) { Point_2 p = polygon.at(i); if (p.x() > crect.xmax()/SF || p.x() < crect.xmin()/SF || p.y() > crect.ymax()/SF || p.y() < crect.ymin()/SF) { std::cerr << "out of bounds" << std::endl; } } } }